原創(chuàng)博客,如有轉(zhuǎn)載蝇完,請注明出處官硝,非常感謝。
首先說一下短蜕,靈感來自于RxAndroid氢架,自從用上了這個庫之后,整個思路都變了朋魔,原來異步還可以玩的這么溜岖研,這還不是重點,重點是我學會了如何使寫代碼更加的流暢警检!
那么除了Rx的異步之外孙援,我究竟學到了什么呢?對的扇雕,就是方法鏈(Method Chaining赃磨,或者叫Named method idiom)和方法參數(shù)盡可能少于等于1個,在鏈條的末端偶爾出現(xiàn)兩三個參數(shù)還是可以接受的洼裤,這兩個點讓我從此代碼風格完全變了邻辉,思路也完全變了!先舉些例子:
- 當你設置全局配置的時候腮鞍,可能會這樣做值骇,并且你一直認為,這樣挺好移国,我也是一直這么認為的:
GlobalConfig.getInstance().setServerInfo("192.168.1.2", 65530, 5 * 60 * 1000, true);
這種風格對我來說吱瘩,有兩個問題,一直困擾我迹缀,但是我居然懶惰的沒去想過解決這兩個困擾我的問題使碾,第一個問題是參數(shù)多蜜徽,哪個對應哪個經(jīng)常記不清楚,需要翻看方法的定義的位置看看票摇,或者鼠標點在方法上拘鞋,再按ctrl之類的一堆快捷鍵看看方法簽名:
public void setServerInfo(String ip, int port, long heartBeatTime, boolean reconnectOnNetworkChange) {
// code comes here
}
哦,原來第一個參數(shù)是ip地址矢门,第二個是端口盆色,第三個是心跳包間隔,第四個是網(wǎng)絡改變的時候是否重連祟剔,大家看到?jīng)]隔躲?記憶力差那么一丁點的時候,必然在這樣的方法調(diào)用時卡你一下物延,而我們的項目里面經(jīng)常充滿這種N個參數(shù)的方法宣旱,每天寫代碼就這樣卡幾次,誰來救救我叛薯?
第二個問題是總感覺有點問題响鹃,就像長城寬帶看高清,總會卡你幾幀案训,寬帶你知道是網(wǎng)絡問題买置,這個代碼有什么問題還一時說不上來,長期習慣了也就覺得强霎,卡一下是應該的忿项,畢竟本人又不是清華北大的高才生,還不是計算機專業(yè)出身的城舞,就像長城寬帶看高清轩触,你交的網(wǎng)費還不到電信的五分之一,偶爾卡一下也能接受家夺。對于方法鏈脱柱,或者有人叫鏈式調(diào)用,我是一直知道的拉馋,并且也在用榨为,各種Builder模式不就是經(jīng)典的代表場景么?Hibernate不是這樣的么煌茴?都習以為常了随闺,要不是RxAndroid給我的震撼感覺,我絕對不會想到蔓腐,上面的代碼應該要重構(gòu)優(yōu)化的>乩帧!回论!現(xiàn)在我的調(diào)用變成了:
GlobalConfig
.getInstance()
.ip("192.168.1.2")
.port(65530)
.heartBeatTime(5 * 60 * 1000)
.reconnectOnNetworkChange(true);
一下子就豁然開朗了散罕,記憶力沒有了負擔分歇,整個人都精神多了,腰也不酸腿也不疼欧漱,媽媽再也不用擔心我沒有名牌大學畢業(yè)了职抡。怎么做到的呢?看重構(gòu)后的代碼(這里為了篇幅去掉了注釋硫椰,不過方法名本身就已經(jīng)非常好的注釋自己了,可能這也是為什么方法鏈有人叫Named method idiom的原因吧):
public GlobalConfig ip(String ip) {
this.ip = ip;
return this;
}
public GlobalConfig port(int port) {
this.port = port;
return this;
}
public GlobalConfig heartBeatTime(long time) {
this.heartBeatTime = time;
return this;
}
public GlobalConfig reconnectOnNetworkChange(boolean reconn) {
this.reconnectOnNetworkChange = reconn;
return this;
}
換個思維萨蚕,生活就是這么幸福靶草。
- 以下場景更常見,創(chuàng)建一個POJO對象岳遥,為對應的字段一一賦值奕翔,沒有哪個場景比這個更常見更習以為常了吧?像這樣:
User user = new User();
user.setName(name);
user.setAge(age);
user.setGender(gender);
// ... 省略更多
UserDao.getInstance().save(user);
有沒有想過可以這樣呢浩蓉?
UserDao.getInstance()
.save(
User.newInstance()
.setName(name)
.setAge(age)
.setGender(gender)
// 省略更多
);
對應的派继,在User這個類里,setter的方法變了捻艳,變成如下:
public User setName(String name) {
this.name = name;
return this;
}
// 其他方法類似驾窟,略去,自行腦補
這時候估計你會跳出來說认轨,我setter方法都是自動生成的绅络,你這不是坑我么?生成setter之后嘁字,我還需要手工去改所有的setter恩急,WTF!
等等纪蜒,我有說這些代碼是我手工寫的么衷恭?Android Studio生成getter/setter的時候本身就自帶這種實現(xiàn),你不看怪我咯纯续,看随珠,連AS都覺得有必要提供這樣的setter生成方式了,不用是不是有點浪費了呢猬错?過程如下:
- 去到你需要生成getter/setter的類牙丽,注意了,操作跟以前是一樣的兔魂,按ALT + Insert鍵烤芦,彈出菜單選擇getter/setter
選擇字段,在setter template那個框選擇Builder析校,然后OK构罗,完成了铜涉,生成的代碼就是上面那種了
以防說的不清楚,有圖有真相:
setter.png
default.png
builder.png
對了遂唧,就是這樣芙代。
- 對于下面這種activity的跳轉(zhuǎn)方法,大家都一致認為是比較不錯的盖彭,至少纹烹,這是目前公認的做的比較合理的一種方式:
// 這個方法是靜態(tài)的,寫在XXXActivity里召边,如果有多種跳轉(zhuǎn)方式的铺呵,寫多個類似的方法
public static void startXXXActivity(Activity fromActivity, String articleId, String thumbImgUrl) {
Intent in = new Intent(fromActivity, XXXActivity.class);
in.putExtra("articleId", articleId);
in.putExtra("thumbImgUrl", thumbImgUrl);
fromActivity.startActivity(in);
}
然后調(diào)用的時候就相對簡單了:
XXXActivity.startXXXActivity(this, "id123456", "http://www.example.com/example.png");
這里的問題跟第一個幾乎是一模一樣的,但是相對于第一種情況隧熙,這里復雜不止一點點片挂,首先,這里有放進Intent的key要管理贞盯,如果很多activity用到的key都相同音念,該抽出來嗎?好吧躏敢,key的問題不展開了闷愤。其次你沒法getInstance(),XXXActivity還沒創(chuàng)造出來呢件余,你怎么使用這個實例來創(chuàng)建方法鏈肝谭?即使你有辦法做出方法鏈,那么多activity蛾扇,你得寫的多累啊攘烛,有了RxAndroid的啟發(fā),我現(xiàn)在是接受不了舊的啟動方式了镀首,怎么辦坟漱?好的,我只好自己寫了一個庫更哄,并且開源了芋齿,托管在github上:SmartKey,大家可以參考一下成翩,如果覺得好請給個星星鼓勵一下觅捆,如果大家有更好的實現(xiàn),也請告訴我一聲麻敌,讓我開開眼界栅炒,提前謝謝大家。終于現(xiàn)在代碼就成了:
SmartTargets.toXXXActivityATarget()
.params(ParamsIBuilder
.newBuilder()
.articleId("id123456")
.thumbImgUrl("http://www.example.com/example.png"))
.go(this);
注意,這里SmartTargets類赢赊、ParamsIBuilder類都是自動生成的乙漓,你要做的就是在你的Application類告訴我,你的manifest文件在哪释移,然后把XXXActivity需要的所有參數(shù)叭披,寫一個叫做Params(名字隨意,N個組件可以公用玩讳,只要是通過Bundle涩蜘、Intent傳遞參數(shù)的都可以用)的非常簡單的連getter/setter都省了的POJO用于描述參數(shù),并且在XXXActivity里可以直接用這個Params類訪問到傳進來的參數(shù)熏纯,至于放進Intent的key同诫,忘掉它吧,你放了參數(shù)進ParamsIBuilder豆巨,在目標Activity就能直接問ParamsIBuilder要回Params對象了剩辟,key的事情掐场,還是不用管最好往扔。關于這個庫,我會再寫兩篇博客詳細說一下熊户,兩篇文章題目都想好了萍膛,分別是:《原來Activity跳轉(zhuǎn)還可以這么舒暢》和《如何優(yōu)雅地管理SharedPreferences》,正在編寫中嚷堡。
好了蝗罗,先寫到這里,總結(jié)一下蝌戒,從RxAndroid我學到的額外東西主要兩個:
第一個是方法鏈串塑,讓你可以專心當前的流程,不再為每次從頭寫變量名等分心了北苟,一直點到目的地桩匪,點到天荒地老,別看這么一點點變化友鼻,就像高手喜歡終端上做關鍵的事情一樣傻昙,減少了例行性的參數(shù)名的編寫就像使用終端減少了鼠標使用減少雙手離開鍵盤一樣,能極大的提高效率彩扔。
第二個是一個方法盡可能的接受更少量的參數(shù)妆档,鏈條內(nèi)盡可能保證少于等于一個參數(shù),末端允許偶爾出現(xiàn)兩個三個的參數(shù)虫碉,再多就要認真想想是不是哪里有問題了贾惦,這樣可以讓你的方法更語義化,方法內(nèi)的職責也可以更加單一化了,這樣可以極大減少記憶力的負擔纤虽,不再需要以前那樣經(jīng)常翻看方法簽名了乳绕,相當于家里的電纜換成了光纖,網(wǎng)絡一下子流暢了逼纸,離準時下班又近一步了洋措。