釋出更新 9/27:改正了讀者指出的錯誤。謝謝大家!還有什麼錯誤和不足儘管指出!
本文中方法適用與Android Studio
和IntelliJ Idea
我們寫程式碼的時候經常要寫個單例,其實在Android Studio中可以快速寫一個單例的方法有很多。
1 從程式碼模版建立一個單例
1.1 從預設單例模版建立一個單例
File
-> New
-> Singleton
。
這是生成單例程式碼的一個例子。
public class Test {
private static Test ourInstance = new Test();
public static Test getInstance() {
return ourInstance;
}
private Test() {
}
}複製程式碼
謝謝讀者提醒!這裡寫錯了!這裡保留原文。下面正文更正!下面程式碼和模版程式碼同時更正,但因篇幅原因,程式碼保留原文了!
原文:這個單例有幾個缺點。getInstance沒有對ourInstance進行空判斷,所以可能返回null。如果加上空判斷,並在其內部如果例項化一個物件就又有一個問題,如果不同步的話可能產生多個物件。所以,Android Studio為我們提供的這個方法並不好。我希望的是這個樣子的:
上面單例是直接賦值的,但是通常,我們都是使用的時候才去賦值,所以通常情況下是下面這個樣子。
public class Test {
private static Test instance ;
public static Test getInstance() {
if (instance == null) {
synchronized (Test.class) {
if (instance == null) {
instance = new Test();
}
}
}
return instance;
}
private Test() {
}
}複製程式碼
1.2 自定義單例模版
既然需求預設的需求不能實現我們的要求,那麼,去自定義單例模版。在 Preference
->Editor
->File and Code Templates
可以找到建立各種File
的模版。如圖:
我們選擇單例,然後在右邊的編輯區就可以編寫自己的程式碼模版。
那麼我這裡提供一套程式碼模版給大家,如果你不願意自己寫,直接把我的複製貼上過去就行了。
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
public class ${NAME} {
private static ${NAME} instance ;
public static ${NAME} getInstance() {
if (instance == null) {
synchronized(${NAME}.class){
if (instance == null) {
instance = new ${NAME}();
}
}
}
return instance;
}
private ${NAME}() {
}
}複製程式碼
然後我們使用這個模版再試一下:
就是我們想要的程式碼。怎麼樣?但是這樣並不總是符合我們的使用場景。我們有的時候,在建立一個類的時候並沒有想好它就是一個單例。有的時候是對一個現有的類的改造。但我們總不能再重新去建立一個吧。
那麼好。看下面。
2 從活動模版重構出一個單例
2.1 自定義活動模版
這個我在我之前的,Android Studio相見恨晚的操作錦集中已經講過一次了,但是為了防止沒有看過那篇文章的讀者我再講一遍。
自定義活動模版的入口:
Prefrence
->Editor
->Live Templates
,下面就是整個介面的一些介紹。
例如我已經在user
組中建立好了自己的singleton
活動模版。如果是你們,可以按照下面步驟做:
- 先點選
+
建立一個新的活動模版 - 然後自己起一個名字
- 描述可以不寫
- 編寫自己的活動模版程式碼
- 有必要的需要在
Edit variables
中編輯函式式
當然我已經編寫好了活動模版程式碼,我貼在這裡,你可以直接複製貼上到自己的裡面:
private static $SELECTION$ instance ;
private $CLASS_NAME$($param1$){
$init$
}
public static $SELECTION$ getInstance($param1$){
if (instance == null) {
synchronized ($CLASS_NAME$.class){
if (instance == null) {
instance = new $CLASS_NAME$($param2$) ;
}
}
}
return instance ;
}複製程式碼
注意 下面一步很關鍵
複製完之後。點選Edit variables
;在CLASS_NAME
對應的後面一格填寫表示式className()
。如圖。
好了大功告成!
2.2 使用自定義模版重構單例程式碼
首先說一下,在我們公司,JavaBean的賦值都是通過依賴注入的方式。幾乎每一個JavaBean都提供了一個介面,單例也是。當然我上面的活動模版也是針對這種情況編寫的,併相容不是依賴注入的情況。
那麼好我們看一個例子:
我們將一個現有的Test類改造成一個單例;
public class Test implements ITest {
private static final String TAG = Test.class.getSimpleName();
public Test(String test) {
init(test);
}
private void init(String test) {
Log.d(TAG, "init: " + test);
}
}複製程式碼
我們的目標應該是將其改造成這樣:
public class Test implements ITest {
private static final String TAG = Test.class.getSimpleName();
private static ITest instance;
private Test(String test) {
init(test);
}
public static ITest getInstance(String test) {
if (instance == null) {
synchronized (Test.class) {
if (instance == null) {
instance = new Test(test);
}
}
}
return instance;
}
private void init(String test) {
Log.d(TAG, "init: " + test);
}
}複製程式碼
OK,那麼看看使用我們的活動模版怎麼做吧!
- 輸入要返回的介面,或者類。(因為我們是依賴注入,所以我寫的介面,如果你不是這樣子,你就寫你要返回的類命就行了)
- 選中剛才輸入的名字。
- 使用
Surround With
,快捷鍵Alt+Command+T
(如果你是windows
,或者快捷鍵不是這個,看下圖,你可以雙擊shift
鍵,輸入surround with
檢視,如果你的紅框部分沒有東西,自己去keymap中去設定吧) - 選擇我們寫好的
singleton
活動模版。就會生成好大部分程式碼。 - 然後跟著游標輸入建構函式中的引數,初始化的方法,getInstance中生成物件要傳入的引數即可。
- 這個時候報錯,沒有關係,因為之前的
public
構造方法沒有刪除。這一步就是刪除原來的public
方法
那麼好,在錄製的時候我故意在關鍵的地方放慢了速度,否則可以更快。這樣是不是可以很快的改造一個單例類了!
3 結束語
我發現我的文章總是被轉成圖片在微博中轉發,在這裡非常感謝大家的賞識。我也希望自己可以給大家分享更多精彩的文章。其實自己在分享的同時也收穫了很多。
但是轉成圖片,就看不到動圖的效果了。有些操作的演示還是很依賴動圖展示的。不過我看轉發我文章的人都會附上原文連結,我在這裡,非常建議大家去看原文。我保證原文更加精彩。
如果你只看到了圖片,那也無所謂了,我的文章暫時也沒有維權呢,那些不帶原文連結和作者資訊的人,他們轉就轉吧,他們開心就好。如果對我們文章感興趣可以到 掘金 中搜尋作者,柴澤建_Jack,就可以檢視我的文章了。
“作者好菜連個連結都不會放嗎?”
“如果生成了圖片你們會去敲連結嗎?”
“會!”
哈哈!我就是“一個逗逼,一個Android開發者,一個持續分享技術乾貨的小浪逼。”
相關閱讀
我其它可能與本文相關的文章。
教你把Java Bean擼成串的最快方法-自定義setter生成指令碼