Github地址:新聞?lì)怉pp (MVP + RxJava + Retrofit+Dagger+ARouter)
列表頁(yè)卡頓優(yōu)化
常規(guī)方案
- convertView復(fù)用, 使用ViewHolder
- 耗時(shí)任務(wù)異步處理
布局相關(guān)
- 減少布局層級(jí),避免過(guò)度繪制
- 異步inflate或者X2C
圖片相關(guān)
- 避免過(guò)大尺寸:GC頻繁,內(nèi)存抖動(dòng)
- 滑動(dòng)時(shí)取消加載
線程相關(guān)
- 使用線程池收斂線程,j降低線程優(yōu)先級(jí)
- 避免UI線程時(shí)間片被搶占
TextView優(yōu)化
- 原因:面對(duì)復(fù)雜文本性能不佳
- 原理:
Boringlayout單行,StaticLayout多行
DynamicLayout可編輯 - 展示類(lèi)StaticLayout即可,性能優(yōu)于DynamicLayout
- 異步創(chuàng)建StaticLayout
- 代碼(項(xiàng)目中不可直接使用)
@Deprecated
public class CustomTextView extends View {
private String text="測(cè)試StaticLayout";
private TextPaint mTextPaint;
private StaticLayout mStaticLayout;
public CustomTextView(Context context) {
this(context,null);
}
public CustomTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLableView();
}
private void initLableView() {
mTextPaint=new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16*getResources().getDisplayMetrics().densityDpi);
mTextPaint.setColor(Color.BLACK);
int width= (int) mTextPaint.measureText(text);
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
mStaticLayout = new StaticLayout(text, mTextPaint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);
postInvalidate();
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mStaticLayout != null){
canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
mStaticLayout.draw(canvas);
canvas.restore();
}
}
}
- 推薦庫(kù):TextLayoutBuilder
Github:https://github.com/facebook/TextLayoutBuilder
其它
- sysTrace跟蹤
- 注意字符串拼接,最好是用StringBuilder
存儲(chǔ)優(yōu)化
常規(guī)方案
- 確保IO操作發(fā)生在非主線程
- Hook或者是AOP輔助
SharePreference相關(guān)
- 加載慢:初始化加載整個(gè)文件
- 全量寫(xiě)入:?jiǎn)未胃膭?dòng)都會(huì)導(dǎo)致整體寫(xiě)入
- 卡頓:補(bǔ)償策略導(dǎo)致
- 不支持跨進(jìn)程通信
SharePreference替代者M(jìn)MKV
- mmap和文件鎖保證數(shù)據(jù)完整
- 增量寫(xiě)入,使用prorocol Buffer
- 支持從SharePreference遷移
- Github:https://github.com/Tencent/MMKV
- 依賴
implementation 'com.tencent:mmkv:1.0.19'
- 代碼
MMKV.initialize(this);
MMKV.defaultMMKV().encode("times",100);
MMKV.defaultMMKV().decodeInt("times");
日志存儲(chǔ)優(yōu)化
大量服務(wù)需要日志庫(kù)支持
對(duì)于性能的要求:不影響性能,日志不丟失,安全
常規(guī)實(shí)現(xiàn)
沒(méi)產(chǎn)生一個(gè)日志,寫(xiě)一遍到磁盤(pán)中:不丟失,性能損耗
開(kāi)辟一個(gè)內(nèi)存buffer,先存buffer,再存文件:丟日志常用數(shù)據(jù)的緩存,避免多次讀取
合理選擇緩沖區(qū)Buffer大小, 4-8kb
WebView異常監(jiān)控
推薦庫(kù):https://github.com/Tencent/VasSonic
- 監(jiān)控屏幕是否白屏,白屏則WebView有問(wèn)題
- 確認(rèn)是白屏,所有像素一致認(rèn)為白屏
- 代碼:webview白屏檢測(cè)
public class BlankDetect {
/**
* 判斷Bitmap是否都是一個(gè)顏色
*/
public static boolean isBlank(View view) {
Bitmap bitmap = getBitmapFromView(view);
if (bitmap == null) {
return true;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
if (width > 0 && height > 0) {
int originPix = bitmap.getPixel(0, 0);
int[] target = new int[width];
Arrays.fill(target, originPix);
int[] source = new int[width];
boolean isWhiteScreen = true;
for (int col = 0; col < height; col++) {
bitmap.getPixels(source, 0, width, 0, col, width, 1);
if (!Arrays.equals(target, source)) {
isWhiteScreen = false;
break;
}
}
return isWhiteScreen;
}
return false;
}
/**
* 從View獲取轉(zhuǎn)換到的Bitmap
*/
private static Bitmap getBitmapFromView(View view){
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
if (Build.VERSION.SDK_INT >= 11) {
view.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(view.getHeight(), View.MeasureSpec.EXACTLY));
view.layout((int) view.getX(), (int) view.getY(), (int) view.getX() + view.getMeasuredWidth(), (int) view.getY() + view.getMeasuredHeight());
} else {
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}
view.draw(canvas);
return bitmap;
}
}