阿里巴巴Android開發(fā)手冊讀后記錄

開發(fā)手冊目前最新的為1.01版.本人閱讀的為正式版第一版1.0.其中許多技巧值得反復(fù)研讀,此文記錄本人認(rèn)為有價(jià)值的知識點(diǎn),部分知識點(diǎn)為延伸知識點(diǎn)

1.Activity & Fragment生命周期再回顧

life_cycle.png

上圖相比于平時(shí)接觸到的多了許多,簡單說幾個(gè):

1)onPostCreate和簸、onPostResume

onPostCreate是指onPostCreate方法是指onCreate方法徹底執(zhí)行完畢的回調(diào)亡电,onPostResume類似髓迎,那我們什么時(shí)候在可以使用這個(gè)呢。大家肯定遇到這種情況禁偎,在onCreate中獲取某個(gè)View的高度和寬度腿堤,發(fā)現(xiàn)獲取到的值是0,因?yàn)檫@個(gè)View可能還沒初始化好如暖,這時(shí)候比如我們在onPostResume中取獲取這個(gè)View的高和寬笆檀,因?yàn)閛nPostResume是指onResume徹底執(zhí)行完畢的回調(diào),所以這時(shí)候去獲取就可以了盒至。

2)onUserInteraction 酗洒,onUserLeaveHint

onUserInteraction我們可以用這個(gè)方法來監(jiān)控用戶有沒有與當(dāng)前的Activity進(jìn)行交互,那我們就可以針對這個(gè)來假設(shè)場景枷遂,有個(gè)APP要求N分鐘后用戶沒有進(jìn)行操作樱衷,那就自動(dòng)出來動(dòng)態(tài)壁紙,或者進(jìn)行鎖屏界面酒唉,或者跳到登錄界面重新登錄等箫老!那我們只需要寫個(gè)倒計(jì)時(shí),然后每次調(diào)用了onUserInteraction方法黔州,就把時(shí)間重置即可。阔籽。多方便A髌蕖!

我們再看onUserLeaveHint:
用戶手動(dòng)離開當(dāng)前activity笆制,會調(diào)用該方法绅这,比如用戶主動(dòng)切換任務(wù),短按home進(jìn)入桌面等在辆。系統(tǒng)自動(dòng)切換activity不會調(diào)用此方法证薇,如來電,滅屏等匆篓。
我們一般監(jiān)聽返回鍵浑度,肯定是重寫onKeyDown方法,但是Home鍵和Menu鍵就不好監(jiān)聽了鸦概。但是有了這個(gè)方法箩张。我們可以做統(tǒng)一的監(jiān)聽了。比如要監(jiān)聽用戶點(diǎn)了Home鍵跳回到桌面后。我們要求這個(gè)APP自動(dòng)跳轉(zhuǎn)到解鎖界面先慷。我們只要在這里做監(jiān)聽出來即可饮笛。

2.添 加 Fragment 時(shí) , 確 保 FragmentTransaction#commit() 在Activity#onPostResume()或者 FragmentActivity#onResumeFragments()內(nèi)調(diào)用。不 要 隨 意 使 FragmentTransaction#commitAllowingStateLoss() 來 代 替 , 任 何commitAllowingStateLoss()的使用必須經(jīng)過 code review,確保無負(fù)面影響论熙。

Activity 可 能 因 為 各 種 原 因 被 銷 毀 , Android 支 持 頁 面 被 銷 毀 前 通 過Activity#onSaveInstanceState()保存自己的狀態(tài)福青。但如果FragmentTransaction.commit()發(fā)生在 Activity 狀態(tài)保存之后,就會導(dǎo)致 Activity 重建、恢復(fù)狀態(tài)時(shí)無法還原頁面狀態(tài),從而可能出錯(cuò)脓诡。為了避免給用戶造成不好的體驗(yàn),系統(tǒng)會拋出 IllegalStateExceptionStateLoss 異常无午。推薦的做法是在 Activity 的onPostResume() 或 onResumeFragments() ( 對 FragmentActivity ) 里 執(zhí) 行FragmentTransaction.commit(),如有必要也可在 onCreate()里執(zhí)行。不要隨意改用FragmentTransaction.commitAllowingStateLoss() 或 者 直 接 使 用 try-catch 避 免crash,這不是問題的根本解決之道,當(dāng)且僅當(dāng)你確認(rèn) Activity 重建誉券、恢復(fù)狀態(tài)時(shí),本次 commit 丟失不會造成影響時(shí)才可這么做指厌。

3.不要在 Activity#onDestroy()內(nèi)執(zhí)行釋放資源的工作,例如一些工作線程的銷 毀 和 停 止 , 因 為onDestroy() 執(zhí) 行 的 時(shí) 機(jī) 可 能 較 晚 。 可 根 據(jù) 實(shí) 際 需 要 , 在Activity#onPause()/onStop()中結(jié)合 isFinishing()的判斷來執(zhí)行踊跟。

4.總是使用顯式 Intent 啟動(dòng)或者綁定 Service,且不要為服務(wù)聲明 Intent Filter,保證應(yīng)用的安全性踩验。如果確實(shí)需要使用隱式調(diào)用,則可為 Service 提供 Intent Filter并從 Intent 中排除相應(yīng)的組件名稱,但必須搭配使用 Intent#setPackage()方法設(shè)置Intent 的指定包名,這樣可以充分消除目標(biāo)服務(wù)的不確定性。

5.當(dāng)前 Activity 的 onPause 方法執(zhí)行結(jié)束后才會執(zhí)行下一個(gè) Activity 的 onCreate方法,所以在 onPause 方法中不適合做耗時(shí)較長的工作,這會影響到頁面之間的跳轉(zhuǎn)效率商玫。

6.【強(qiáng)制】不要在 Android 的 Application 對象中緩存數(shù)據(jù)箕憾。基礎(chǔ)組件之間的數(shù)據(jù)共享請使用 Intent 等機(jī)制,也可使用 SharedPreferences 等數(shù)據(jù)持久化機(jī)制.

7.Activity 或者 Fragment 中動(dòng)態(tài)注冊 BroadCastReceiver 時(shí), registerReceiver()和 unregisterReceiver()要成對出現(xiàn)拳昌。

說明:
如果 registerReceiver()和 unregisterReceiver()不成對出現(xiàn),則可能導(dǎo)致已經(jīng)注冊的
receiver 沒有在合適的時(shí)機(jī)注銷,導(dǎo)致內(nèi)存泄漏,占用內(nèi)存空間,加重 SystemService
負(fù)擔(dān)袭异。
部分華為的機(jī)型會對 receiver 進(jìn)行資源管控,單個(gè)應(yīng)用注冊過多 receiver 會觸發(fā)管
控模塊拋出異常,應(yīng)用直接崩潰。
正例:

public class MainActivity extends AppCompatActivity {
private static MyReceiver myReceiver = new MyReceiver();

@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("com.example.myservice");
registerReceiver(myReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(myReceiver);
}
...
}

反例:

public class MainActivity extends AppCompatActivity {
private static MyReceiver myReceiver;
@Override
protected void onResume() {
super.onResume();
myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter("com.example.myservice");
registerReceiver(myReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myReceiver);
}
}

8.在 Activity 中顯示對話框或彈出浮層時(shí),盡量使用 DialogFragment,而非Dialog/AlertDialog,這樣便于隨 Activity 生命周期管理對話框/彈出浮層的生命周期炬藤。

9.盡量不要使用 AnimationDrawable,它在初始化的時(shí)候就將所有圖片加載到內(nèi)存中,特別占內(nèi)存,并且還不能釋放,釋放之后下次進(jìn)入再次加載時(shí)會報(bào)錯(cuò)御铃。

說明:
Android 的幀動(dòng)畫可以使用 AnimationDrawable 實(shí)現(xiàn),但是如果你的幀動(dòng)畫中如果
包含過多幀圖片,一次性加載所有幀圖片所導(dǎo)致的內(nèi)存消耗會使低端機(jī)發(fā)生 OOM
異常。幀動(dòng)畫所使用的圖片要注意降低內(nèi)存消耗,當(dāng)圖片比較大時(shí),容易出現(xiàn) OOM沈矿。
圖片數(shù)量較少的 AnimationDrawable 還是可以接受的上真。

10.【推薦】新建線程時(shí),定義能識別自己業(yè)務(wù)的線程名稱,便于性能優(yōu)化和問題排查。

public class MyThread extends Thread {
public MyThread(){
super.setName("ThreadName");
...
}
}

11.【推薦】謹(jǐn)慎使用 Android 的多進(jìn)程,多進(jìn)程雖然能夠降低主進(jìn)程的內(nèi)存壓力,但會遇到如下問題:

  1. 不能實(shí)現(xiàn)完全退出所有 Activity 的功能;
  2. 首次進(jìn)入新啟動(dòng)進(jìn)程的頁面時(shí)會有延時(shí)的現(xiàn)象(有可能黑屏羹膳、白屏幾秒,是白屏還是黑屏和新 Activity 的主題有關(guān));
  3. 應(yīng)用內(nèi)多進(jìn)程時(shí),Application 實(shí)例化多次,需要考慮各個(gè)模塊是否都需要在所有進(jìn)程中初始化;
  4. 多進(jìn)程間通過 SharedPreferences 共享數(shù)據(jù)時(shí)不穩(wěn)定睡互。

12.【 推 薦 】 SharedPreference 提 交 數(shù) 據(jù) 時(shí) , 盡 量 使 用 Editor#apply() , 而 非Editor#commit()。一般來講,僅當(dāng)需要確定提交結(jié)果,并據(jù)此有后續(xù)操作時(shí),才使用 Editor#commit()陵像。說明:SharedPreference 相關(guān)修改使用 apply 方法進(jìn)行提交會先寫入內(nèi)存,然后異步寫入磁盤,commit 方法是直接寫入磁盤就珠。如果頻繁操作的話 apply 的性能會優(yōu)于 commit,apply 會將最后修改內(nèi)容寫入磁盤。但是如果希望立刻獲取存儲操作的結(jié)果,并據(jù)此做相應(yīng)的其他操作,應(yīng)當(dāng)使用 commit醒颖。

正例:

public void updateSettingsAsync() {
SharedPreferences mySharedPreferences = getSharedPreferences("settings",
Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putString("id", "foo");
editor.apply();
}
public void updateSettings() {
SharedPreferences mySharedPreferences = getSharedPreferences("settings",
Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putString("id", "foo");
if (!editor.commit()) {
Log.e(LOG_TAG, "Failed to commit setting changes");
}
}

反例:

editor.putLong("key_name", "long value");
editor.commit();

13.【強(qiáng)制】在 Activity.onPause()或 Activity.onStop()回調(diào)中,關(guān)閉當(dāng)前 activity 正在執(zhí)行的的動(dòng)畫妻怎。

14.【推薦】使用 ARGB_565 代替 ARGB_888,在不怎么降低視覺效果的前提下,減少內(nèi)存占用。

說明:
android.graphics.Bitmap.Config 類中關(guān)于圖片顏色的存儲方式定義:

  1. ALPHA_8 代表 8 位 Alpha 位圖;
  2. ARGB_4444 代表 16 位 ARGB 位圖;
  3. ARGB_8888 代表 32 位 ARGB 位圖;
  4. RGB_565 代表 8 位 RGB 位圖泞歉。

位圖位數(shù)越高,存儲的顏色信息越多,圖像也就越逼真蹂季。大多數(shù)場景使用的是
ARGB_8888 和 RGB_565,RGB_565 能夠在保證圖片質(zhì)量的情況下大大減少內(nèi)存
的開銷,是解決 oom 的一種方法冕广。
但是一定要注意 RGB_565 是沒有透明度的,如果圖片本身需要保留透明度,那么
就不能使用 RGB_565。
正例:

Config config = drawableSave.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 :
Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);

反例:

Bitmap newb = Bitmap.createBitmap(width, height, Config.ARGB_8888);

15.【推薦】在有強(qiáng)依賴 onAnimationEnd 回調(diào)的交互時(shí),如動(dòng)畫播放完畢才能操作頁面 , onAnimationEnd 可 能 會 因 各 種 異 常 沒 被 回 調(diào) ( 參 考 :https://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-called-onanimationstart-works-fine ), 建 議 加 上 超 時(shí) 保 護(hù) 或 通 過 postDelay 替 代onAnimationEnd偿洁。

正例:

View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
public void run() {
if (v != null) {
v.clearAnimation();
}
}
}, anim.getDuration());
v.startAnimation(anim);

參考:
超詳細(xì)的生命周期圖-你能回答全嗎

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撒汉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涕滋,更是在濱河造成了極大的恐慌睬辐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宾肺,死亡現(xiàn)場離奇詭異溯饵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锨用,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門丰刊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人增拥,你說我怎么就攤上這事啄巧。” “怎么了掌栅?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵秩仆,是天一觀的道長。 經(jīng)常有香客問我猾封,道長澄耍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任晌缘,我火速辦了婚禮齐莲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磷箕。我一直安慰自己铅搓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布搀捷。 她就那樣靜靜地躺著,像睡著了一般多望。 火紅的嫁衣襯著肌膚如雪嫩舟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天怀偷,我揣著相機(jī)與錄音家厌,去河邊找鬼。 笑死椎工,一個(gè)胖子當(dāng)著我的面吹牛饭于,可吹牛的內(nèi)容都是我干的蜀踏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼掰吕,長吁一口氣:“原來是場噩夢啊……” “哼果覆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起殖熟,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤局待,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后菱属,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钳榨,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年纽门,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了薛耻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赏陵,死狀恐怖饼齿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘟滨,我是刑警寧澤候醒,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站杂瘸,受9級特大地震影響倒淫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜败玉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一敌土、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧运翼,春花似錦返干、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悠夯,卻和暖如春癌淮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沦补。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工乳蓄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夕膀。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓虚倒,卻偏偏與公主長得像美侦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子魂奥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容