App的優化目的是為了讓應用更快、更穩定、更小。網上也有很多相應的文章,但是很多因為花費時間跟優化程度不成正比,或者許多在開發過程中自己已經避免了所以僅僅記錄一下自己最近用過的。
更快
啟動白屏
<!--啟動activity時白屏替換-->
<style name="SplashStyle" parent="AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!--如果需要效果更圓滑可以換成啟動頁的背景圖-->
<item name="android:windowBackground">@color/theme_color</item>
<!--帶有這個屬性就會去除劉海屏-->
<item name="android:windowFullscreen">true</item>
</style>
複製程式碼
把啟動頁的主題換成
<activity
android:name=".SplashActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/SplashStyle"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
複製程式碼
注意
- 可能有些人直接換MainActivity的主題,這樣會有些問題,背景在啟動後處需要換過來。並且不能設定去除劉海屏的屬性,有些手機不適配,劉海屏處是白的。可能是我自己沒有找到控制劉海屏的方法。希望大佬指點一下
- 跳轉到MainActivity不能直接把啟動頁finish掉,否則跳轉時會有一瞬間白屏。需要延時幾秒finish
//延時銷燬,避免白屏
new Handler().postDelayed(() -> {
finish();
}, 3000);
複製程式碼
- 跳轉時最好換一下系統預設的跳轉動畫,效果會比較圓滑
ARouter.getInstance().build(RouterPath.MAIN)
.withTransition(R.anim.common_popup_fade_in, R.anim.common_popup_fade_out)
.navigation(this);
複製程式碼
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/decelerate_interpolator"
android:toAlpha="0.0"/>
複製程式碼
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="@android:anim/decelerate_interpolator"
android:toAlpha="1.0"/>
複製程式碼
延時載入
/**
* 螢幕以外資訊延時獲取
*/
private void initDelay() {
// 拿到主執行緒的MessageQueue
Looper.myQueue().addIdleHandler(() -> {
// 最後返回false,後續不用再監聽了。
return faslse;
});
}
複製程式碼
addIdleHandler 方法是當handle執行緒空閒再執行,基本上可以理解為介面顯示後再執行。具體原理可以看mp.weixin.qq.com/s/KpeBqIEYe…
非同步載入
對於一些沒必要在主執行緒執行的程式碼,如sp、資料庫等程式碼可以在子執行緒初始化。
佈局優化
看看是否過度繪製以及巢狀層級是否過多。這種一般在寫程式碼時注意一下後期可以避免很多工作。
- 同一層級時LinearLayout、FrameLayout比RelativeLayout效能要好。
- 寫佈局時background可避免的儘量不設定
- 靈活使用ViewStub,例項化才載入並且只載入一次。
一些其他
點選事件優化
很多app沒有做點選誤差處理,所以有時候點選兩次會出現兩個介面,雖然影響不大但是為了讓使用者體驗更好。最好一開始就做好
- 使用RxBind具體看github
- 使用工具類
public class ViewOnClickUtils {
private static final int MIN_DELAY_TIME= 1000; // 兩次點選間隔不能少於1000ms
private static long lastClickTime;
/**
* 判斷是否快速點選
* @return
*/
public static boolean isFastClick() {
boolean flag = true;
long currentClickTime = System.currentTimeMillis();
if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) {
flag = false;
}
lastClickTime = currentClickTime;
return flag;
}
/**
* 判斷是否快速點選
* @param time 設定時間
* @return
*/
public static boolean isFastClick(int time) {
boolean flag = true;
long currentClickTime = System.currentTimeMillis();
if ((currentClickTime - lastClickTime) >= time) {
flag = false;
}
lastClickTime = currentClickTime;
return flag;
}
}
複製程式碼
tv.setOnClickListener(view -> {
if (ViewOnClickUtils.isFastClick()) {
return;
}
//邏輯操作
...
}
複製程式碼
圖片壓縮
更小的圖片意味著載入更快,上傳也更快。
- 以前在外包公司做的時候,ui給的圖片很大,沒有做到最大限度的壓縮,一個背景圖幾百k,載入的時候回出現記憶體抖動,所以最好叫UI或者自己去網上找一下壓縮。
- 圖片上傳時也應該使用壓縮,一款非常棒的圖片壓縮開源框架github.com/Curzibn/Lub…
更穩定
避免記憶體洩漏、記憶體抖動。我個人覺得這跟平時寫程式碼比較相關
注意
- 需要傳入Context的地方,需要注意生命週期是否一致。比如單例應該用ApplicationContext
- 註冊的監聽需要銷燬時反註冊,或者迴圈播放的動畫銷燬時要記得停止寫自定義view時尤其注意。
- 避免在短時間內大量建立物件,比如寫列表時如果有這種需要可以使用單例代替或者做好判斷。
出現卡頓是我們需要一些工具的輔助排查
- 經常用到LeakCanary,用於看是否有記憶體洩漏。一般一開始就會接入。接入方式可以看看部落格www.jianshu.com/p/70b8c87ea…
- 其他一些工具的介紹例如as自帶的monnitors和MAT(memoryAnalyzer:eclipse官方工具) www.jianshu.com/p/d71b51a0e…
崩潰問題
雖然在測試階段已經會把這個過濾掉,但是實際使用時可能資料出錯等等的原因都可能導致崩潰。這時我們最好接入Bugly,接入方法可以看官網,每次崩潰bugly都會記錄。但是bugly每天只會推送一次,如果我們需要做一些預警,可以監聽app崩潰做個通知發給釘釘機器人或者我們自己的後臺方便我們做熱修復。
釘釘群截圖如下,具體實現可以看對應官方文件以及部落格。相對來說比較簡單沒什麼技術含量,只是提供個方案。
更小
可以去除沒用的佈局、資源以及庫加上程式碼混淆。一般公司可能用不到外掛化我也不是很熟悉。
程式碼混淆
篇幅較長不做過多講解,學習混淆最主要的是知道混淆原則,就是哪些不應該被混淆。
混淆參考部落格
- Android studio自帶混淆
- 第三方混淆
建議閱讀
關於效能優化的系列文章可以看看他寫的文章有效能優化設計模式等等。