本文中方法適用與Android Studio
和IntelliJ Idea
我們寫代碼的時(shí)候經(jīng)常要寫個(gè)單例展箱,其實(shí)在Android Studio中可以快速寫一個(gè)單例的方法有很多叛复。
1 從代碼模版創(chuàng)建一個(gè)單例
1.1 從默認(rèn)單例模版創(chuàng)建一個(gè)單例
File
-> New
-> Singleton
。
這是生成單例代碼的一個(gè)例子械哟。
public class Test {
private static Test ourInstance = new Test();
public static Test getInstance() {
return ourInstance;
}
private Test() {
}
}
謝謝讀者提醒!這里寫錯(cuò)了!這里保留原文映凳。下面正文更正!下面代碼和模版代碼同時(shí)更正录别,但因篇幅原因耕渴,代碼保留原文了!
原文:這個(gè)單例有幾個(gè)缺點(diǎn)拘悦。getInstance沒有對(duì)ourInstance進(jìn)行空判斷,所以可能返回null橱脸。如果加上空判斷础米,并在其內(nèi)部如果實(shí)例化一個(gè)對(duì)象就又有一個(gè)問題,如果不同步的話可能產(chǎn)生多個(gè)對(duì)象添诉。所以屁桑,Android Studio為我們提供的這個(gè)方法并不好。我希望的是這個(gè)樣子的:
上面單例是直接賦值的栏赴,但是通常蘑斧,我們都是使用的時(shí)候才去賦值,所以通常情況下是下面這個(gè)樣子须眷。
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 自定義單例模版
既然需求默認(rèn)的需求不能實(shí)現(xiàn)我們的要求竖瘾,那么,去自定義單例模版花颗。在 Preference
->Editor
->File and Code Templates
可以找到創(chuàng)建各種File
的模版准浴。如圖:
我們選擇單例,然后在右邊的編輯區(qū)就可以編寫自己的代碼模版捎稚。
那么我這里提供一套代碼模版給大家,如果你不愿意自己寫求橄,直接把我的復(fù)制粘貼過去就行了今野。
#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}() {
}
}
然后我們使用這個(gè)模版再試一下:
就是我們想要的代碼。怎么樣罐农?但是這樣并不總是符合我們的使用場(chǎng)景条霜。我們有的時(shí)候,在創(chuàng)建一個(gè)類的時(shí)候并沒有想好它就是一個(gè)單例涵亏。有的時(shí)候是對(duì)一個(gè)現(xiàn)有的類的改造宰睡。但我們總不能再重新去創(chuàng)建一個(gè)吧。
那么好气筋〔鹉冢看下面。
2 從活動(dòng)模版重構(gòu)出一個(gè)單例
2.1 自定義活動(dòng)模版
這個(gè)我在我之前的宠默,Android Studio相見恨晚的操作錦集中已經(jīng)講過一次了麸恍,但是為了防止沒有看過那篇文章的讀者我再講一遍。
自定義活動(dòng)模版的入口:
Prefrence
->Editor
->Live Templates
,下面就是整個(gè)界面的一些介紹抹沪。
例如我已經(jīng)在user
組中創(chuàng)建好了自己的singleton
活動(dòng)模版刻肄。如果是你們,可以按照下面步驟做:
- 先點(diǎn)擊
+
創(chuàng)建一個(gè)新的活動(dòng)模版 - 然后自己起一個(gè)名字
- 描述可以不寫
- 編寫自己的活動(dòng)模版代碼
- 有必要的需要在
Edit variables
中編輯函數(shù)式
當(dāng)然我已經(jīng)編寫好了活動(dòng)模版代碼融欧,我貼在這里敏弃,你可以直接復(fù)制粘貼到自己的里面:
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 ;
}
注意 下面一步很關(guān)鍵
復(fù)制完之后。點(diǎn)擊Edit variables
噪馏;在CLASS_NAME
對(duì)應(yīng)的后面一格填寫表達(dá)式className()
麦到。如圖。
好了大功告成!
2.2 使用自定義模版重構(gòu)單例代碼
首先說一下逝薪,在我們公司隅要,JavaBean的賦值都是通過依賴注入的方式。幾乎每一個(gè)JavaBean都提供了一個(gè)接口董济,單例也是步清。當(dāng)然我上面的活動(dòng)模版也是針對(duì)這種情況編寫的,并兼容不是依賴注入的情況虏肾。
那么好我們看一個(gè)例子:
我們將一個(gè)現(xiàn)有的Test類改造成一個(gè)單例廓啊;
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);
}
}
我們的目標(biāo)應(yīng)該是將其改造成這樣:
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,那么看看使用我們的活動(dòng)模版怎么做吧!
- 輸入要返回的接口封豪,或者類谴轮。(因?yàn)槲覀兪且蕾囎⑷耄晕覍懙慕涌诖挡海绻悴皇沁@樣子第步,你就寫你要返回的類命就行了)
- 選中剛才輸入的名字。
- 使用
Surround With
缘琅,快捷鍵Alt+Command+T
(如果你是windows
粘都,或者快捷鍵不是這個(gè),看下圖刷袍,你可以雙擊shift
鍵翩隧,輸入surround with
查看,如果你的紅框部分沒有東西呻纹,自己去keymap中去設(shè)置吧) - 選擇我們寫好的
singleton
活動(dòng)模版堆生。就會(huì)生成好大部分代碼。 - 然后跟著光標(biāo)輸入構(gòu)造函數(shù)中的參數(shù)雷酪,初始化的方法淑仆,getInstance中生成對(duì)象要傳入的參數(shù)即可。
- 這個(gè)時(shí)候報(bào)錯(cuò)太闺,沒有關(guān)系糯景,因?yàn)橹暗?code>public構(gòu)造方法沒有刪除。這一步就是刪除原來的
public
方法
那么好,在錄制的時(shí)候我故意在關(guān)鍵的地方放慢了速度蟀淮,否則可以更快最住。這樣是不是可以很快的改造一個(gè)單例類了!