單例模式是一種軟體設計模式,規則是每個類別只能有一個實例存在,並且能提供全域訪問。當多個類別呼叫它時,拿到的都會是同一個實例。該singleton類別可以自己產生一個自己的實例,也可以透過工廠類別來產生。
在一個典型的APP中,我們常只需要物件的一個全域實例,無論是直接使用它還是簡單地將它傳遞給另一個類。包括OkHttpClient, HttpLoggingInterceptor, retrofit,Gson,SharedPreferences和倉庫類等。 如果我們把這些類產生實體了多個物件,我們就會遇到許多問題,比如異常的APP反應,資源過度使用和其他混亂的結果。
public class Singleton{
private static Singleton instance = null;
private Singleton(){
//構造函數
}
private synchronized static void createInstance(){
if(instance == null){
instance = new Singleton();
}
}
public static Singleton getInstance(){
if(instance == null) createInstance();
return instance;
}
}
class MainActivity : AppCompatActivity() {
object test{
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
一行程式碼,結束。
object
關鍵字代表其包含了上面單例的特性。我們試著把它decompile就會變成下面這樣。public static final class test {
public static final MainActivity.test INSTANCE;
private test() {
}
static {
MainActivity.test var0 = new MainActivity.test();
INSTANCE = var0;
}
}
那如果我們想在static區塊加入更多東西,好讓他們在app一開啟就被執行呢?
寫在init{}
初始化區塊裡就可以啦~
object test{
init{
println("init")
}
fun wangwang(){
println("wangwang")
}
}
decompile之後
public static final class test {
public static final MainActivity.test INSTANCE;
public final void wangwang() {
String var1 = "wangwang";
System.out.println(var1);
}
//構造函數一定是空的
private test() {
}
static {
MainActivity.test var0 = new MainActivity.test();
INSTANCE = var0;
String var1 = "init";
System.out.println(var1);
}
}
}
那類別加載的時候就初始化構造單例,是不是對空間的利用不太好?
這一點問題不大,虛擬機在運行程序的時候,並不是在啟動時就將所有的類別都初始化完成,而是在真正使用它的時候才會初始化。