當前位置:首頁 » 安卓系統 » 單例模式android

單例模式android

發布時間: 2023-06-15 01:53:13

① 結合Android看看單例模式怎麼寫

單例模式常見的兩種實現方式 餓漢模式和 雙重鎖模式
•餓漢模式
public class HungrySingleton {
private static HungrySingleton mInstance = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return mInstance;
}
}
不得不說,餓漢模式這個名字起得的確很巧,這種方式,不管你用不用得著這個實例,先給你創建(new)出來,生怕將來創建沒機會似得,完全就是今朝有酒今朝醉的節奏。
與上面對應的還有一種就是懶漢模式,就是在用的時候才在getInstance 方法中完成實例的創建(new),真是「懶」,同時給這個方法添加synchronized 關鍵字,可以確保在多線程情況下單例依舊唯一,但是懶漢模式每次調用getInstance 方法時由於synchronized 的存在,需要進行同步,造成不必要的資源開銷。因此便有了下面雙重鎖模式的實現方式。
•雙重鎖模式(DCL 實現)
public class LazySingleton {
private static LazySingleton mInstance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (mInstance == null) {
synchronized (LazySingleton.class) {
if (mInstance == null) {
mInstance = new LazySingleton();
}
}
}
return mInstance;
}
}
這樣既避免了餓漢模式的缺點,又解決了懶漢模式的不足;確保單例只在第一次真正需要的時候創建。
Android 中的使用
在日常的Android開發中,也可以見到單例模式的身影。
•Glide
使用Glide載入圖片非常方便,大家應該不陌生,可以看一下它的源碼中單例模式的實現方式。
Glide.with(this).load(url).into(imageView);
//Glide.with()
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
//RequestManagerRetriever.get()
/** The singleton instance of RequestManagerRetriever. */
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
/**
* Retrieves and returns the RequestManagerRetriever singleton.
*/
public static RequestManagerRetriever get() {
return INSTANCE;
}
可以看到,當我們寫下Glide.with(..) 這行代碼時,就完成了RequestManagerRetriever 這個類的實例化,這個類的單例模式是使用餓漢模式實現的。
•EventBus
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
};
很明顯,EventBus的單例模式使用雙重鎖模式實現的。
•InputMethodManager static InputMethodManager sInstance
public static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
sInstance = new InputMethodManager(service, Looper.getMainLooper());
}
return sInstance;
}
}
InputMethodManager 的單例模式是使用懶漢模式實現。
可以看到,關於單例模式的實現方式,面對不同的場景,我們可以做出不同的選擇
•Glide的單例模式雖然是使用餓漢模式實現,但理論上來說並不會造成內存資源的浪費,因為當我們通過gradle的配置引入Glide的庫時,就是為了載入圖片,必然會使用Glide.with進行相關的操作。同時RequestManagerRetriever 這個類應該是一個網路請求的管理類(Glide源碼沒有研究過,這里只是猜測),這樣的一個類必然需要使用單列模式,試想如果存在多個管理類的實例,那麼談何管理,那麼的多Request到底聽哪個manger 的,這就是前面提到必須使用單列模式的情景。

•EventBus 作為事件匯流排的更要使用單例模式了,如果說EventBus的實例不是單例模式,那麼他就無法實現它的功能了。對於EventBus不了解的同學,可以看看
EventBus 3.0 相見恨晚,EventBus真的很強大。

•InputMethodManager 使用懶漢模式實現單例也是無可厚非的,畢竟誰會去頻繁的獲取那麼多他的實例呢;同時作為一個系統的輸入法管理器,他也必須是唯一的,因此這個類也需要單例模式來實現它唯一的實例供外部使用。

由上可見,關於單例模式的實現,沒有說哪一種方式最好,只有最合適的實現方式;實際開發中,單例模式應該怎麼寫,還需要根據業務場景做最合適的選擇,無論是餓漢懶漢實用才是好漢。個人感覺,餓漢模式是一種簡單又方便的實現方式, 一個類既然已經寫成了單例模式,必然是要使用的呀,誰會去創建一個餓漢模式的單例,又不去使用這個單例呢?
之前在使用Volley的時候,就是使用餓漢模式創建整個應用的RequestQueue單例,所有需要網路請求的地方,把request添加到RequestQueue單例中即可。
public class MyApplication extends Application{
// 建立請求隊列
public static RequestQueue queue;
@Override
public void onCreate() {
super.onCreate();
queue = Volley.newRequestQueue(getApplicationContext());
}
public static RequestQueue getHttpQueue() {
return queue;
}
}
在應用Application的onCreate方法中創建了屬於整個應用的queue,之後每一次網路請求時,只需要queue.add(Request)即可,這里使用單例模式,可以有效的避免在多個地方創建RequestQueue 的實例,浪費系統資源。

② android 幾種單例模式的寫法

先不論單例模式的寫法,有些方面是相同的,比如都需要將唯一的對象設置為static的,都需要將構造方法private化,代碼如下:
public class MyInstance { private static MyInstance instance; private MyInstance(){}
}
第一種:最原始的單例模式,代碼如下:
public static MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();
} return instance;
}
多線程並發時,可能會出現重復new對象的情況,因此不提倡使用。
第二種:將整個方法塊進行加鎖,保證線程安全。
public static synchronized MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();
} return instance;
}

這種代碼下,每條線程都會依次進入方法塊內部,雖然實現了單例,但是影響了運行效率,可以使用但是也不怎麼提倡。
第三種:進一步優化的方法。
public static MyInstance getsInstance(){ synchronized (MyInstance.class){ if(instance==null){ instance=new MyInstance(); return instance;
}else{ return instance;
}
}
}

這種方式只是第二種方法的一種優化,但是優化有限。
(以下的幾種方法比較推薦使用)
第四種:雙層判斷加鎖,效率影響小且保證了線程安全。
public static MyInstance getsInstance() { if (instance == null) { synchronized (MyInstance.class) { if(instance==null){ instance=new MyInstance();
}
}
} return instance;
}

這種方法是對第二種和第三種方法的進一步優化,比較推薦使用。
第五種:內部類實現單例,不用線程鎖來實現效率的提升。
public class MyInstance { private MyInstance() {
} public static MyInstance getInstance(){ return MyInstanceHolder.instance;
} private static class MyInstanceHolder{ private static MyInstance instance=new MyInstance();
}
}

在內部類中new對象,再將內部類的對象返回,這種方法是使用了java中class載入時互斥的原理來實現了線程的安全。不加線程鎖也使得運行效率不會受到較大的影響。比較提倡。

③ Android中單例模式和靜態方法在效率上哪個好

很多人包括我寫單例的時候,第一想到的就是懶漢式publicclassSingleton{;privateSingleton(){}(){if(instance==null){instance=newSingleton();}returninstance;}}代碼很簡單,而且是懶載入,只有調用getInstance方法是才會初始化。但是這樣是線程不安全的,即當多個線程並行調用getInstance的時候,就會創建多個實例,不能正常工作。所以這里就有了加鎖方式,將整個getInstance方法設為同步,添加synchronized關鍵字。publicclassSingleton{;privateSingleton(){}(){if(instance==null){instance=newSingleton();}returninstance;}}這樣簡單粗暴的方式,雖然做到了線程安全,但導致了同一時間內只能有一個線程能夠調用getInstance方法。其實我們僅僅需要對初始化的代碼進行同步,這就有了雙重檢驗鎖方式。publicclassSingleton{;privateSingleton(){}(){if(instance==null){//第一次檢查synchronized(Singleton.class){if(instance==null){//第二次檢查instance=newSingleton();}}}returninstance;}}這里第二次檢查,是因為如果有多個線程同時執行完了第一次檢查,這時如果同步塊內不進行第二次檢查的話,會生成多個實例了。但是看了相關資料後,發現這樣還是有點問題。引用資料中的介紹:由於instance=newSingleton(),這並非是一個原子操作,事實上在JVM中這句話大概做了下面3件事情。1.給instance分配內存2.調用Singleton的構造函數來初始化成員變數3.將instance對象指向分配的內存空間(執行完這步instance就為非null了)但是在JVM的即時編譯器中存在指令重排序的優化。也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是1-2-3也可能是1-3-2。如果是後者,則在3執行完畢、2未執行之前,被線程二搶佔了,這時instance已經是非null了(但卻沒有初始化),所以線程二會直接返回instance,然後使用,然後順理成章地報錯。我們只需要將instance變數聲明成volatile就可以了。

④ 了解過哪些android設計模式分別詳細說一下優缺點

  1. Builder模式:比如AlertDialog.Builder;例簡單模擬Android中AlertDialog的Builder設計模式

  2. 適配器模式:比如GridView、ListView與Adapter;例Android設計模式系列(9)--SDK源碼之適配器模式

  3. 命令模式:比如Handler.post;例命令模式下的非同步消息處理(Handler,Message,Looper,Thread)

  4. 享 元模式:Android和設計模式:享元模式

  5. 單 例模式:比如InputMethodManager.getInstance,例Android源碼學習之單例模式應用

  6. 觀察者模式:比如ContentObserver;例Android中內容觀察者的使用---- ContentObserver類詳解

  7. 抽象工廠模式:比如BaseActivity,例Android Ap 開發 設計模式第八篇:抽象工廠模式

  8. 我經常用到的就上面這些,設計模式並不是很神秘的東西,我們在寫程序的過程中可能每天都在用設計模式,只是沒有用設計模式的專業術語來稱呼它。我現在越來越感覺到編程方法和設計模式非常重要,因為它能夠指導你寫出較高質量的代碼、避免一些前人遇到過的坑,當你借用這些方法和模式寫出一段代碼,提供給別人使用和回味的時候會很有成就感。程序員都應該去有意地接觸這方面的知識,比如高內聚、低耦合、封裝變化,在設計介面的時候都是非常重要的原則。

⑤ Android 開發中常用到的設計模式有哪些

設計模式總共是23種,常用的有下面幾種 :
1 單例模式,application 就是單例 可以存儲一些數據例如記錄activity的啟動數量 ;
2 觀察者模式: button的onClickListener ,監聽button的響應;
3 適配器模式 :例如recyclerView 的adapter ;
4 命令模式: 例如開源庫eventBus ,把數據封裝好 發送出去,然後接收; 等等等等,很多

⑥ android之單例模式:懶漢式和餓漢式的區別

比較:
餓漢式是線程安全的,在類創建的同時就已經創建好一個靜態的對象供系統使用,以後不在改變。
懶漢式如果在創建實例對象時不加上synchronized則會導致對對象的訪問不是線程安全的。

熱點內容
android設置靜音 發布:2025-02-07 20:11:53 瀏覽:696
bin存儲 發布:2025-02-07 20:00:50 瀏覽:205
android載入界面 發布:2025-02-07 19:55:28 瀏覽:872
好礦雲伺服器 發布:2025-02-07 19:54:31 瀏覽:950
java電話簿 發布:2025-02-07 19:49:26 瀏覽:798
超級腳本製作 發布:2025-02-07 19:31:30 瀏覽:487
怎麼查看支付寶的賬號密碼 發布:2025-02-07 19:26:48 瀏覽:17
惠普伺服器查看ip指令 發布:2025-02-07 19:26:47 瀏覽:435
演算法設計模式 發布:2025-02-07 19:15:52 瀏覽:746
伺服器1u能連接幾台電腦 發布:2025-02-07 18:50:02 瀏覽:154