優化ViewPager 左右滑動卡頓問題

優化ViewPager 左右滑動卡頓問題

在項目中,使用到ViewPager控件,突然發現左右滑動到某個頁面出現卡頓現象,
ViewPager 已使用緩存策略,切換卡片也不會重新刷新界面,應該不是主動刷新View引起,查看日誌打印也印證了這點,沒辦法只能硬着頭皮查找View刷新邏輯,發現ViewPager 在左右滑動會輪尋計算子View,會做計算和比較,
可能是這裏耗時,回過頭再對比同一個頁面顯示不同的View,卡頓效果不同,只有某個ViewGroup 顯示卡頓明顯,細看xml發現該ViewGroup嵌套較深,重新修改嵌套邏輯再次測試發現有效果,就這樣重新提交代碼。

突然領導半夜發微信,說卡頓現象任然存在,心想不可能啊,自己都已經使用真機測試,優化效果很明顯,那爲什麼領導還會覺得卡頓呢。也只能帶着疑問睡覺了。

第二天,使用復現問題機器對照測試發現卡頓真的還存在,只是沒有先前那麼明顯,回來細看代碼發現沒有問題,整個佈局嵌套也已優化到兩層,按理說不會存在卡頓現象,沒辦法,只好再次查看Android源碼View刷新流程,希望能找到點蛛絲馬跡,果不其然,在一個刷新方法裏面注意到了這一個邏輯

 /**
     * Manually render this view (and all of its children) to the given Canvas.
     * The view must have already done a full layout before this function is
     * called.  When implementing a view, implement
     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
     * If you do need to override this method, call the superclass version.
     *
     * @param canvas The Canvas to which the View is rendered.
     */
    @CallSuper
    public void draw(Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

        /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      3. Draw view's content
         *      4. Draw children
         *      5. If necessary, draw the fading edges and restore layers
         *      6. Draw decorations (scrollbars for instance)
         */

        // Step 1, draw the background, if needed
        int saveCount;

        if (!dirtyOpaque) {
            drawBackground(canvas);
        }

        // skip step 2 & 5 if possible (common case)
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        if (!verticalEdges && !horizontalEdges) {
            // Step 3, draw the content
            if (!dirtyOpaque) onDraw(canvas);

            // Step 4, draw the children
            dispatchDraw(canvas);

            drawAutofilledHighlight(canvas);

            // Overlay is part of the content and draws beneath Foreground
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }

            // Step 6, draw decorations (foreground, scrollbars)
            onDrawForeground(canvas);

            // Step 7, draw the default focus highlight
            drawDefaultFocusHighlight(canvas);

            if (debugDraw()) {
                debugDrawFocus(canvas);
            }

            // we're done...
            return;
        }
       ..................................
       ..................................
    }
 /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      3. Draw view's content
         *      4. Draw children
         *      5. If necessary, draw the fading edges and restore layers
         *      6. Draw decorations (scrollbars for instance)
         */

分析draw 方法,發現繪製的第一步就是繪製背景,可能是這裏耗時,經過查看xml發現該佈局View背景都有設置,那我是不是可以在這個點優化一下呢,於是把View 背景設置去掉,去掉冗餘大背景,修改ImageView 背景改成src 設置,儘快修改,測試發現去掉xml的背景,滑動頁面不卡頓了。

切記,xml佈局嵌套不要太多,同一個佈局,子View 背景不要設置太多

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章