Android 代碼Review清單

自測清單

開發(fā)結(jié)束后假夺,開發(fā)人員做好以下自測點(diǎn),保證提測質(zhì)量

  1. 對照需求文檔斋攀,測試邏輯是否吻合完整
  2. 對可能有問題的地方進(jìn)行簡單的壓力測試已卷,是否會出現(xiàn)閃退Bug
  3. 對照Umeng或者Bugly開發(fā)階段出現(xiàn)的閃退bug是否都已解決
  4. 檢測UI是否有變形,比如常見的TextView淳蔼,是否需要行數(shù)限制侧蘸,文字太多,是否或出現(xiàn)頁面顯示異常
  5. 在不同分辨率的機(jī)型上鹉梨,檢查布局是否有Bug,特別是現(xiàn)在全面屏讳癌,劉海屏,需要有全屏操作是存皂,在有虛擬導(dǎo)航欄的手機(jī)上的適配問題
  6. 版本升級,從低版本升級上來析桥,會不會有問題 比如可能會出現(xiàn)數(shù)據(jù)庫不兼容的問題
  7. 利用手機(jī)的開發(fā)者選項中的 “調(diào)試GPU過度繪制” ,“GPU呈現(xiàn)模式分析” 和 “顯示FPS和功耗” 功能艰垂,看自己的新功能是否會導(dǎo)致過度繪制、是否會掉幀
  8. app業(yè)務(wù)斷網(wǎng)埋虹,再聯(lián)網(wǎng)猜憎,相關(guān)業(yè)務(wù)是否正常。

Review清單

清理操作

  1. Activity退出銷毀操作
     * 是否調(diào)用Handler的removeCallbacksAndMessages(null)來清空Handler里的消息搔课;
     * 是否取消了還沒完成的請求胰柑;
     * 在頁面里注冊的監(jiān)聽,是否反注冊;
     * 假如自己用到觀察者模式柬讨,是否反注冊崩瓤;
     * 假如用了RxJava的話,是否解除訂閱踩官;
  1. 數(shù)據(jù)庫的游標(biāo)是否已經(jīng)關(guān)閉
  2. 打開過的文件流是否關(guān)閉
  3. WebView使用完是否調(diào)用了其destory()函數(shù)
  4. Bitmap是否調(diào)用recycle
    Android 3.0以下的版本却桶,使用完的Bitmap是否調(diào)用recycle(),否則會一直占用內(nèi)存 而Android 3.0及以上的版本不需要調(diào)用recycle()蔗牡,因?yàn)檫@些版本的Bitmap全部放到虛擬機(jī)的堆內(nèi)存中颖系,讓GC自動回收。

代碼性能優(yōu)化

  1. 檢查是否使用多余的for循環(huán)辩越,UI線程是否有耗時操作
  2. 是否可以用String代替StringBuilder,是否可以用StringBuilder代替StringBuffer
  3. 保存在內(nèi)存中的圖片嘁扼,是否做過壓縮處理再保存在內(nèi)存里 否則可能由于圖片質(zhì)量太高,導(dǎo)致OOM
  4. Intent傳遞的數(shù)據(jù)太大黔攒,會導(dǎo)致頁面跳轉(zhuǎn)過慢趁啸。太大的數(shù)據(jù)可以通過持久化的形式傳遞,例如讀寫文件或者是否實(shí)現(xiàn)Parcelable
  5. 頻繁地操作同一個文件或者執(zhí)行同一個數(shù)據(jù)庫操作督惰,是否考慮把它用靜態(tài)變量或者局部變量的形式緩存在內(nèi)存里不傅。用空間換時間
  6. Listview或者RecycleView的item中,bindData的時候姑丑,避免SharePreference的讀取或者存儲操作,是否可以采用全局變量來解決
  7. Sqlite數(shù)據(jù)庫增刪改查是否處理了多線程訪問的并非操作蛤签,建議采用事務(wù)處理,高效栅哀,盡量用synchronized震肮,效率太慢
  8. 頁面布局,是否可以考慮用ViewStub來優(yōu)化啟動速度
  9. xml中的布局文件是否有多余的嵌套留拾,影響性能

gradle第三方依賴包

  1. build.gradle遠(yuǎn)程依賴第三方包時戳晌,版本號建議寫死,不要使用+號 避免由于新版本的第三方包引入了新的問題
  2. 調(diào)用第三方的包或者JDK的方法時痴柔,要跳進(jìn)他們的源碼沦偎,看要不要加 try-catch 否則可能會導(dǎo)致自己應(yīng)用的崩潰
  3. 使用第三方包時,是否加上其混淆規(guī)則 若漏掉加上第三方包的混淆規(guī)則咳蔚,會導(dǎo)致第三方包不該混淆的代碼被混淆豪嚎。在Debug版本沒有發(fā)現(xiàn)問題,但是Release版本就會出現(xiàn)問題

檢查成對的方法是否同時出現(xiàn)

  1. 系統(tǒng)的谈火、自己寫的侈询,注冊和反注冊的方法,是否成對出現(xiàn)
  2. 在生命周期的回調(diào)里糯耍,創(chuàng)建和銷毀的代碼是否對應(yīng)起來 比如:onCreate()里面創(chuàng)建了Adapter扔字,那么對應(yīng)Adapter的退出處理操作(比如清空Image緩存)囊嘉,一般就要寫在onDestory(),而不能寫在onDestoryView()革为。
  3. 若ListView的item復(fù)用了瓷耙,對Item里View的操作是否成對出現(xiàn) 比如:
switch (type) {    
case ArticleListItem.TYPE_AD:        ......        
   mTitleView.setText(tencentAdBean.title);        
   mGreenLabelView.setVisibility(VISIBLE);        
   mRedLabelView.setText("");        
   mRedLabelView.setVisibility(GONE);    
   break;    
case ArticleListItem.TYPE_ARTICLE:        ......        
   mTitleView.setText(mzAdBean.adData.getTitle());        
   mGreenLabelView.setVisibility(GONE);        
   mRedLabelView.setText("ABC");        
   mRedLabelView.setVisibility(VISIBLE);        
   break;
}

內(nèi)存泄漏

  1. 內(nèi)部類播瞳,比如Handler埃唯、Listener懂诗、Callback是否是成static class 因?yàn)榉庆o態(tài)內(nèi)部類會持有外部類的引用】叶祝或者在頁面銷毀的時候虐块,是否設(shè)置listener,CallBack等為null
  2. 要求傳入Activity作為參數(shù)的函數(shù),是否可以改用getApplicationContext()來作為參數(shù),比如數(shù)據(jù)庫嘉蕾,SharePreference,getSystemService等
//Kotlin代碼
private val mAudioManager = context.applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
private val sp=context.applicationContext.getSharedPreferences(name, Context.MODE_PRIVATE)
  1. 單例模式不要持有Activity的引用贺奠,同時要記得注冊和反注冊的監(jiān)聽,如下:
QmPayHelper.getInstance().setPayListener(object: onPayListener{
 override fun onWxPay(){
 }
})

一定要在頁面銷毀的時候错忱,設(shè)置為null,不然因?yàn)閛nPayListener持有Activity的引用而內(nèi)存泄漏

QmPayHelper.getInstance().setPayListener(null)
  1. 每次Activity關(guān)閉的時候儡率,Handler相關(guān)的操作是否需要移除:
 mHandler.removeCallbacksAndMessages(null)
  1. 頁面關(guān)閉的時候,如果有動畫在執(zhí)行以清,是否清除相關(guān)動畫,比如:
@Override
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak);
        textView = (TextView)findViewById(R.id.text_view);
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,"rotation",0,360);
        objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
        objectAnimator.start();
    }

@Override
 protected void onDestroy(){
        super.onDestroy();
        //取消動畫
        objectAnimator.cancel();
    } 

Handler操作

  1. Handler使用的時候是否采用靜態(tài)內(nèi)部類以及當(dāng)前類弱引用的方式出現(xiàn),如下:
//Kotlin代碼
inner class KpcHandler(controller: QmPlayerController) : Handler() {
        private var mWrf = WeakReference(controller)
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            val controller = mWrf.get()
            controller?.hide()
        }
  }
  1. 使用View.post()是否會有問題 因?yàn)樵赩iew處于detached狀態(tài)期間儿普,post()里面的Runnable是不會被執(zhí)行的。只有在此View處于attached狀態(tài)時才會被執(zhí)行掷倔。
    如果想改Runnable每次肯定會被執(zhí)行眉孩,那么應(yīng)該是用Handler.post來替代:
 Handler(Looper.myLooper()).post {  } //Kotlin代碼
  1. 假如程序可能多次在同一個Handler里post同一個Runnable,每次post之前都應(yīng)該先清空這個Handler中還沒執(zhí)行的該Runnable 如:
if (mCloudRun != null) {    
     mHandler.removeCallbacks(mCloudRun);    
     mCloudRun = null;}
mCloudRun = new Runnable() {    
     @Override   
     public void run() {        
            CloudAccelerateSwitchRequest request = new CloudAccelerateSwitchRequest();   
            request.setPriority(RequestTask.PRIORITY_LOW);     
            RequestQueue.getInstance().addRequest(request);   
     }
};
mHandler.post(mCloudRun);   

高概率閃退點(diǎn)以及邏輯健全Review

  1. 除數(shù)是否做了非0判斷
  2. 某些情況下勒葱,某變量是否會為Null,而且在函數(shù)體內(nèi)浪汪,處理參數(shù)前,必須加上判空語句
  3. 異步回調(diào)函數(shù)是否處理好,回調(diào)函數(shù)很容易出問題凛虽。比如網(wǎng)絡(luò)請求的回調(diào)死遭,需要判斷此時的Aciivity或者Fragment等是否還存在,再進(jìn)行調(diào)用凯旋。因?yàn)楫惒讲僮骰貋硌教叮珹ctivity可能就消失不存在了。 而且還要對一些可能被回收的變量進(jìn)行判空至非。
  4. 修改數(shù)據(jù)庫后钠署,是否把數(shù)據(jù)庫的版本號+1,升級邏輯是否處理合理
  5. 啟動第三方的Activity時荒椭,是否判斷了該Intent能否被解析
Intent sendIntent = new Intent(mContext, Demo.class);
// 這種方式判斷是否存在
if (sendIntent.resolveActivity(getPackageManager()) != null) {  
  startActivity(sendIntent);
}

若Activity不存在谐鼎,會出現(xiàn)ActivityNotFoundException的異常

  1. 檢查if()邏輯后是否處理了else()的相關(guān)操作,比如常見的操作,listview中的item復(fù)用的時候,如下:
if(hasTitle){
   mTitleView.setText(tencentAdBean.title);        
   mGreenLabelView.setVisibility(VISIBLE);        
}else{
  //如果不處理,則mTitleView可能會不顯示
   mTitleView.setText("");        
   mGreenLabelView.setVisibility(GONE);    
}
  1. 不要在Activity的onCreate里調(diào)用PopupWindow的showAsLoaction方法戳杀,由于Activity還沒被加載完该面,會報錯
  2. 系統(tǒng)6.0的動態(tài)權(quán)限申請,7.0的文件訪問信卡,8.0的通知欄渠道channel等適配操作是否完善

參考:https://juejin.im/entry/5ba998f6f265da0aa74f2a76

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末隔缀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子傍菇,更是在濱河造成了極大的恐慌猾瘸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丢习,死亡現(xiàn)場離奇詭異牵触,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咐低,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門揽思,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人见擦,你說我怎么就攤上這事钉汗。” “怎么了鲤屡?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵损痰,是天一觀的道長。 經(jīng)常有香客問我酒来,道長卢未,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任堰汉,我火速辦了婚禮辽社,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衡奥。我一直安慰自己爹袁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布矮固。 她就那樣靜靜地躺著失息,像睡著了一般。 火紅的嫁衣襯著肌膚如雪档址。 梳的紋絲不亂的頭發(fā)上盹兢,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音守伸,去河邊找鬼绎秒。 笑死,一個胖子當(dāng)著我的面吹牛尼摹,可吹牛的內(nèi)容都是我干的见芹。 我是一名探鬼主播剂娄,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼玄呛!你這毒婦竟也來了阅懦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤徘铝,失蹤者是張志新(化名)和其女友劉穎耳胎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惕它,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怕午,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了淹魄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郁惜。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖揭北,靈堂內(nèi)的尸體忽然破棺而出扳炬,到底是詐尸還是另有隱情,我是刑警寧澤搔体,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布恨樟,位于F島的核電站,受9級特大地震影響疚俱,放射性物質(zhì)發(fā)生泄漏劝术。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一呆奕、第九天 我趴在偏房一處隱蔽的房頂上張望养晋。 院中可真熱鬧,春花似錦梁钾、人聲如沸绳泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽零酪。三九已至,卻和暖如春拇勃,著一層夾襖步出監(jiān)牢的瞬間四苇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工方咆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留月腋,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像榆骚,于是被迫代替她去往敵國和親片拍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,501評論 25 707
  • 用兩張圖告訴你妓肢,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料穆碎? 從這篇文章中你...
    hw1212閱讀 12,693評論 2 59
  • 一 朗讀者第一季的時候,自小學(xué)業(yè)優(yōu)秀职恳,耶魯大學(xué)畢業(yè)的秦玥飛沒有選擇做都市白領(lǐng),而是投身鄉(xiāng)村方面,做了湖南一個村子的村官...
    唐夕閱讀 873評論 0 2
  • 已經(jīng)安裝 composer放钦,寫好 composer.bat,并且設(shè)置好了 path恭金,在 cmd 下可以正常使用操禀,但...
    guanguans閱讀 2,605評論 0 2
  • sentinel的一個缺點(diǎn)是存儲容量限于單臺機(jī)器,而集群提供了一種分布式的解決方案横腿。 redis有兩種運(yùn)行模式1)...
    packet閱讀 406評論 0 0