新聞?lì)怉pp (MVP + RxJava + Retrofit+Dagger+ARouter)性能優(yōu)化之其他優(yōu)化

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();
        }
    }
}

其它

  • 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,再存文件:丟日志

  • mmap
    內(nèi)存映射文件
    優(yōu)勢(shì):高性能,不丟失
    推薦庫(kù):Xlog,Logan

  • 常用數(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;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容