我们如何优化(cpu& ram)这个android自定义初始化动画?

时间:2016-04-01 16:20:44

标签: android animation optimization android-animation android-canvas

我为Splash Screen活动开发了一个自定义动画:

=>这是一个动画,显示正在发生的事情:

enter image description here

当然是我的真实应用:

  • 有不同的图片(fullhd)
  • 与GIF相比有点慢:60个中间屏幕为3秒。

我的设计师为我提供了60个png文件。

=>举例说明:

enter image description here

我的目标是:

  1. 从带有底部图片的中央徽标(此处带有SO)开始 (苹果)
  2. 运行变形动画
  3. 在屏幕上结束,就像应用主页一样
  4. 为了运行它,我有一个SpashScreenActivity的多层布局:

    • BackGround(不可见):homePage(MainActivity)的布局
    • MiddleGround:Apple的ImageView被Droid和bottomBar取代而成长
    • FrontGround:ImageView中的徽标,其标语为TextView

    以下是SpashScreen布局的xml代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="invisible"
            android:orientation="vertical">
    
            <FrameLayout
                android:id="@+id/fl_logo_top_marge_hidden"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:visibility="invisible"
                android:background="@color/colorPrimary" />
    
            <include
                android:visibility="invisible"
                android:id="@+id/l_logo_activate_hidden"
                layout="@layout/part_logo_activate"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <FrameLayout
                android:visibility="invisible"
                android:id="@+id/fl_logo_bottom_marge_hidden"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="@color/colorPrimary" />
    
            <fr.millezimsolutions.app.splashanimation.SquareAspectWidthBasedImageView
                android:visibility="invisible"
                android:id="@+id/iv_home_hidden"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="fitXY"
                android:src="@drawable/p_log_android" />
    
            <FrameLayout
                android:visibility="invisible"
                android:id="@+id/fl_bar_hidden"
                android:layout_width="match_parent"
                android:layout_height="@dimen/start_degustation_bar_height"
                android:background="@color/colorAccent"
                android:gravity="bottom" />
        </LinearLayout>
    
    
        <LinearLayout
            android:id="@+id/fl_middle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentBottom="true"
            android:background="@color/colorPrimary"
            android:gravity="bottom"
            android:orientation="vertical">
    
            <fr.millezimsolutions.app.splashanimation.FitXCropTopImageView
                android:id="@+id/iv_slogan"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorTransparent"
                android:scaleType="fitStart"
                android:src="@drawable/p_log_apple" />
    
            <FrameLayout
                android:id="@+id/fl_logo_bottom_bar"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:background="@color/colorAccent"
                android:gravity="bottom" />
    
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/fl_front"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <FrameLayout
                android:id="@+id/fl_logo_top_layout"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="40"
                android:background="@color/colorPrimary" />
    
            <FrameLayout
                android:id="@+id/fl_logo_top_marge"
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:background="@color/colorTransparent" />
    
            <include
                android:id="@+id/l_logo_activate"
                layout="@layout/part_logo_activate"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <FrameLayout
                android:id="@+id/fl_logo_bottom_marge"
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:background="@color/colorTransparent" />
    
            <FrameLayout
                android:id="@+id/fl_logo_bottom_layout"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="40"
                android:background="@color/colorTransparent" />
        </LinearLayout>
    </RelativeLayout>
    

    2布局顶部的xml代码(通过include)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorTransparent"
        android:gravity="bottom"
        android:orientation="vertical">
    
        <FrameLayout
            android:id="@+id/fl_home_marginTop"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    
        <ImageView
            android:id="@+id/iv_millezimuLogo"
            android:layout_width="wrap_content"
            android:layout_height="64dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginLeft="@dimen/marge"
            android:layout_marginRight="@dimen/marge"
            android:src="@drawable/p_log_so" />
    
        <TextView
            android:id="@+id/tv_slogan"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="@dimen/marge_small"
            android:layout_marginTop="@dimen/marge_small_border"
            android:gravity="center"
            android:hint=""
            android:text="Bonjour"
            android:textColor="@color/colorAccent"
            android:textSize="20sp" />
    
        <ImageView
            android:id="@+id/iv_sponsorLogo"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginLeft="@dimen/marge"
            android:layout_marginRight="@dimen/marge"
            android:src="@drawable/p_log_so"
            android:visibility="gone" />
    
        <TextView
            android:id="@+id/tv_sponsorLogo"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginLeft="@dimen/marge"
            android:layout_marginRight="@dimen/marge"
            android:gravity="center"
            android:textColor="@color/colorAccent"
            android:textSize="20sp"
            android:visibility="gone" />
    
        <FrameLayout
            android:id="@+id/fl_home_marginBottom"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    
    </LinearLayout>
    

    3以下是活动的代码。

     import android.content.Intent; 
     import android.graphics.Bitmap;
     import android.graphics.Canvas;
     import android.graphics.Paint;
     import android.graphics.PorterDuff;
     import android.graphics.PorterDuffXfermode;
     import android.graphics.Rect;
     import android.os.Bundle;
     import android.os.Handler;
     import android.support.v7.app.AppCompatActivity;
     import android.util.Log;
     import android.view.ViewGroup;
     import android.view.WindowManager;
     import android.widget.FrameLayout;
     import android.widget.ImageView;
     import android.widget.LinearLayout;
    
     public class SplashScreenActivity extends AppCompatActivity {
    
        // Splash screen timer
        private static int SPLASH_TIME_OUT = 3000;
        private int finalTopMarge, finalBottomMarge, topMargeDec, bottomMargeInc;
        long currentTimeStamp;
    
        private int[] mSplashAnimFrames = {R.drawable.p_wave_spashscreen_00, R.drawable.p_wave_spashscreen_01, R.drawable.p_wave_spashscreen_02, R.drawable.p_wave_spashscreen_03, R.drawable.p_wave_spashscreen_04, R.drawable.p_wave_spashscreen_05, R.drawable.p_wave_spashscreen_06, R.drawable.p_wave_spashscreen_07, R.drawable.p_wave_spashscreen_08, R.drawable.p_wave_spashscreen_09,
                R.drawable.p_wave_spashscreen_10, R.drawable.p_wave_spashscreen_11, R.drawable.p_wave_spashscreen_12, R.drawable.p_wave_spashscreen_13, R.drawable.p_wave_spashscreen_14, R.drawable.p_wave_spashscreen_15, R.drawable.p_wave_spashscreen_16, R.drawable.p_wave_spashscreen_17, R.drawable.p_wave_spashscreen_18, R.drawable.p_wave_spashscreen_19,
                R.drawable.p_wave_spashscreen_20, R.drawable.p_wave_spashscreen_21, R.drawable.p_wave_spashscreen_22, R.drawable.p_wave_spashscreen_23, R.drawable.p_wave_spashscreen_24, R.drawable.p_wave_spashscreen_25, R.drawable.p_wave_spashscreen_26, R.drawable.p_wave_spashscreen_27, R.drawable.p_wave_spashscreen_28, R.drawable.p_wave_spashscreen_29,
                R.drawable.p_wave_spashscreen_30, R.drawable.p_wave_spashscreen_31, R.drawable.p_wave_spashscreen_32, R.drawable.p_wave_spashscreen_33, R.drawable.p_wave_spashscreen_34, R.drawable.p_wave_spashscreen_35, R.drawable.p_wave_spashscreen_36, R.drawable.p_wave_spashscreen_37, R.drawable.p_wave_spashscreen_38, R.drawable.p_wave_spashscreen_39,
                R.drawable.p_wave_spashscreen_40, R.drawable.p_wave_spashscreen_41, R.drawable.p_wave_spashscreen_42, R.drawable.p_wave_spashscreen_43, R.drawable.p_wave_spashscreen_44, R.drawable.p_wave_spashscreen_45, R.drawable.p_wave_spashscreen_46, R.drawable.p_wave_spashscreen_47, R.drawable.p_wave_spashscreen_48, R.drawable.p_wave_spashscreen_49,
                R.drawable.p_wave_spashscreen_50, R.drawable.p_wave_spashscreen_51, R.drawable.p_wave_spashscreen_52, R.drawable.p_wave_spashscreen_53, R.drawable.p_wave_spashscreen_54, R.drawable.p_wave_spashscreen_55, R.drawable.p_wave_spashscreen_56, R.drawable.p_wave_spashscreen_57, R.drawable.p_wave_spashscreen_58, R.drawable.p_wave_spashscreen_59};
    
    
        private final int C_STOP = 120, C_MOVE = 40, C_BAR = 80;
        private int bottomBarRatio;
        private ImageView finalImageView;
        private int targetWidth, targetHeight;
        private Rect mImageViewRect;
        private Paint paint;
        private Bitmap original;
        private Bitmap result;
        private boolean setupOk = false;
        private ImageView mImageView;
        private Bitmap mask;
        private FrameLayout ltm;
        private FrameLayout lbm;
        private FrameLayout lbb;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_splash_screen);
    
            // Indique que l'ecran est full Screen
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    
            ImageManager.create(this);
    
        }
    
    
        @Override
        protected void onResume() {
            super.onResume();
            int delay = SPLASH_TIME_OUT / C_STOP;
            bottomBarRatio = getResources().getDimensionPixelSize(R.dimen.bar_nav_height) / (C_STOP - C_BAR);
            runCycle(0, delay);
        }
    
    
        private void logStamp() {
            long oldTimeStamp = currentTimeStamp;
            currentTimeStamp = System.currentTimeMillis();
            long delay = currentTimeStamp - oldTimeStamp;
            Log.v("TIMESTAMP", String.valueOf(delay));
        }
    
        public void runCycle(final int cycle, final int delay) {
            if (BuildConfig.DEBUG)
                logStamp();
    
            Handler cyclic = new Handler();
            cyclic.postDelayed(new Runnable() {
    
                @Override
                public void run() {
    
                    if (cycle >= C_STOP) {
                        closeActivity();
                    } else {
                        runCycle(cycle + 1, delay);
    
                        if (cycle >= C_MOVE) {
                            // Copy des hauteurs pour les marges
                            initFinalLogoMargeHeight();
    
                            // Decroissance du poid de layout superieur
                            MoveUpLogo();
    
                            // bouger la bar
                            if (cycle >= C_BAR) {
                                updateBottomBar(cycle - C_BAR);
                            }
                            findViewById(R.id.fl_front).requestLayout();
                        }
    
                        if (setupFinalView()) {
                            if ((cycle % 2) == 0)
                                updateImageViewLight(cycle / 2);
                        }
                    }
                }
    
            }, delay);
        }
    
    
        private boolean setupFinalView() {
            if (!setupOk) {
                finalImageView = (ImageView) findViewById(R.id.iv_home_hidden);
                targetWidth = finalImageView.getWidth();
                targetHeight = finalImageView.getHeight();
                mImageViewRect = new Rect(0, 0, finalImageView.getWidth(), finalImageView.getHeight());
                mImageView = (ImageView) findViewById(R.id.iv_slogan);
                mImageView.setBackgroundResource(R.drawable.p_log_apple);
    
                paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
                ltm = (FrameLayout) findViewById(R.id.fl_logo_top_marge);
                lbm = (FrameLayout) findViewById(R.id.fl_logo_bottom_marge);
                lbb = ((FrameLayout) findViewById(R.id.fl_logo_bottom_bar));
    
    
                if (targetWidth > 0 && targetHeight > 0) {
                    original = ImageManager.decodeSampledBitmapFromResource(getResources(), R.drawable.p_log_android, targetWidth, targetHeight);
                    result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_4444);
                    setupOk = true;
                }
            }
            return setupOk;
        }
    
        private void MoveUpLogo() {
            ViewGroup.LayoutParams ltmp = ltm.getLayoutParams();
            ltmp.height -= topMargeDec;
    
            ViewGroup.LayoutParams lbmp = lbm.getLayoutParams();
            lbmp.height += bottomMargeInc;
        }
    
    
        private void initFinalLogoMargeHeight() {
            if (finalBottomMarge == 0) {
                finalTopMarge = findViewById(R.id.fl_logo_top_marge_hidden).getHeight();
                topMargeDec = (findViewById(R.id.fl_logo_top_marge).getHeight() - finalTopMarge) / C_BAR;
                finalBottomMarge = findViewById(R.id.fl_logo_bottom_marge_hidden).getHeight() + findViewById(R.id.fl_bar_hidden).getHeight() + findViewById(R.id.iv_home_hidden).getHeight();
                bottomMargeInc = (finalBottomMarge - findViewById(R.id.fl_logo_bottom_marge).getHeight()) / C_BAR;
            }
        }
    
        private void updateBottomBar(int cycle) {
            LinearLayout.LayoutParams lbbp = (LinearLayout.LayoutParams) lbb.getLayoutParams();
            lbbp.height = cycle * bottomBarRatio;
            lbb.setLayoutParams(lbbp);
        }
    
    
        private void closeActivity() {
            overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
            Intent i = new Intent(SplashScreenActivity.this, MainActivity.class);
            startActivity(i);
            finish();
            overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
        }
    
        private int getNext(int index) {
            if (index < (mSplashAnimFrames.length - 1))
                index++;
            else
                index = mSplashAnimFrames.length - 1;
            return mSplashAnimFrames[index];
        }
    
    
        public void updateImageViewLight(int index) {
    
            mask = ImageManager.decodeSampledBitmapFromResource(getResources(), getNext(index), targetWidth, targetHeight);
            Canvas mCanvas = new Canvas(result);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mCanvas.drawBitmap(original, null, mImageViewRect, null);
            mCanvas.drawBitmap(mask, null, mImageViewRect, paint);
            paint.setXfermode(null);
            mImageView.setImageBitmap(result);
        }
    
    }
    

    4用于理解的ImageManager代码(我使用UIL)

    public class ImageManager {
    
    
        private static Context context;
    
        public static ImageLoader getImageLoader() {
            return ImageLoader.getInstance();
        }
    
        public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                             int reqWidth, int reqHeight) {
    
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.outWidth = reqWidth;
            options.outHeight = reqHeight;
            options.inJustDecodeBounds = true;
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            BitmapFactory.decodeResource(res, resId, options);
    
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            return getResourceImageForCanvas(resId, new ImageSize(reqWidth, reqHeight));
        }
    
        public static int calculateInSampleSize(
                BitmapFactory.Options options, int reqWidth, int reqHeight) {
            // Raw height and width of image
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;
    
            if (height > reqHeight || width > reqWidth) {
    
                final int halfHeight = height / 2;
                final int halfWidth = width / 2;
    
                // Calculate the largest inSampleSize value that is a power of 2 and keeps both
                // height and width larger than the requested height and width.
                while ((halfHeight / inSampleSize) > reqHeight
                        && (halfWidth / inSampleSize) > reqWidth) {
                    inSampleSize *= 2;
                }
            }
    
            return inSampleSize;
        }
    
    
    
        public static Bitmap getResourceImageForCanvas(int bitmapResourceId, ImageSize targetImageSize) {
            DisplayImageOptions options = new DisplayImageOptions.Builder().bitmapConfig(Bitmap.Config.RGB_565).build();
            return getImageLoader().loadImageSync("drawable://" + bitmapResourceId, targetImageSize, options);
    //
        }
    
        public static void create(Context context) {
            try {
                ImageManager.context = context;
                initImageLoader();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private static void initImageLoader() throws IOException {
            // Create global configuration and initialize ImageLoader with this
            // configuration
    
            BitmapFactory.Options opt = new BitmapFactory.Options();
            // opt.inScaled = false;
            opt.inSampleSize = 1;
            opt.inDither = true;
            opt.inPreferredConfig = Bitmap.Config.RGB_565;
            opt.inPreferQualityOverSpeed = false;
    
            DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()./* cacheInMemory(true). */cacheOnDisk(true).decodingOptions(opt).imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                    .bitmapConfig(Bitmap.Config.RGB_565).build();
    
            ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context).defaultDisplayImageOptions(defaultOptions).memoryCacheSizePercentage(13).writeDebugLogs().build();
            ImageLoader.getInstance().init(config);
        }
    
    }
    

    状态:

    updateImageViewLight方法可以帮助其他人处理这种不容易找到的行为(PortedDuff ...)。

    动画在功能强大的设备上运行良好,但如果设备或应用程序执行其他操作,则通常会滞后。

    我曾尝试在异步任务中运行此计算,但功能不如mainThread

    问题:

    我正在寻找有关我的实施的任何有根据的建议,这可能有助于改善:

    • 内存消耗
    • CPU使用率

    但是:

    • 潜在泄漏
    • 代码可读性

1 个答案:

答案 0 :(得分:3)

尚未完全回答,但这是一次尝试,需要继续和评论。

首次优化:

  • 为wave创建自定义视图(此处为ImageView扩展名),将在onDraw方法
  • 上刷新
  • 将const成员定义为static final类成员
  • 尽可能
  • 尽可能避免在onDrawCanvasPaint)中创建对象实例以及不必要的对象更新

以下是扩展ImageView的CustomView的代码

    public class WaveFillingImageView extends ImageView {

    private final static int[] mSplashAnimFrames = {R.drawable.p_wave_spashscreen_00, R.drawable.p_wave_spashscreen_01, R.drawable.p_wave_spashscreen_02, R.drawable.p_wave_spashscreen_03, R.drawable.p_wave_spashscreen_04, R.drawable.p_wave_spashscreen_05, R.drawable.p_wave_spashscreen_06, R.drawable.p_wave_spashscreen_07, R.drawable.p_wave_spashscreen_08, R.drawable.p_wave_spashscreen_09,
            R.drawable.p_wave_spashscreen_10, R.drawable.p_wave_spashscreen_11, R.drawable.p_wave_spashscreen_12, R.drawable.p_wave_spashscreen_13, R.drawable.p_wave_spashscreen_14, R.drawable.p_wave_spashscreen_15, R.drawable.p_wave_spashscreen_16, R.drawable.p_wave_spashscreen_17, R.drawable.p_wave_spashscreen_18, R.drawable.p_wave_spashscreen_19,
            R.drawable.p_wave_spashscreen_20, R.drawable.p_wave_spashscreen_21, R.drawable.p_wave_spashscreen_22, R.drawable.p_wave_spashscreen_23, R.drawable.p_wave_spashscreen_24, R.drawable.p_wave_spashscreen_25, R.drawable.p_wave_spashscreen_26, R.drawable.p_wave_spashscreen_27, R.drawable.p_wave_spashscreen_28, R.drawable.p_wave_spashscreen_29,
            R.drawable.p_wave_spashscreen_30, R.drawable.p_wave_spashscreen_31, R.drawable.p_wave_spashscreen_32, R.drawable.p_wave_spashscreen_33, R.drawable.p_wave_spashscreen_34, R.drawable.p_wave_spashscreen_35, R.drawable.p_wave_spashscreen_36, R.drawable.p_wave_spashscreen_37, R.drawable.p_wave_spashscreen_38, R.drawable.p_wave_spashscreen_39,
            R.drawable.p_wave_spashscreen_40, R.drawable.p_wave_spashscreen_41, R.drawable.p_wave_spashscreen_42, R.drawable.p_wave_spashscreen_43, R.drawable.p_wave_spashscreen_44, R.drawable.p_wave_spashscreen_45, R.drawable.p_wave_spashscreen_46, R.drawable.p_wave_spashscreen_47, R.drawable.p_wave_spashscreen_48, R.drawable.p_wave_spashscreen_49,
            R.drawable.p_wave_spashscreen_50, R.drawable.p_wave_spashscreen_51, R.drawable.p_wave_spashscreen_52, R.drawable.p_wave_spashscreen_53, R.drawable.p_wave_spashscreen_54, R.drawable.p_wave_spashscreen_55, R.drawable.p_wave_spashscreen_56, R.drawable.p_wave_spashscreen_57, R.drawable.p_wave_spashscreen_58, R.drawable.p_wave_spashscreen_59};
    private Paint paint;
    private long nextDrawTimeStamp;
    private boolean init = false, isStarted = false;
    private Bitmap original, result;
    private Rect mImageViewRect;
    private int index = 0;
    private LogAndStat las;
    private Canvas mCanvas;
    private  final int timeTick = 50;

    public WaveFillingImageView(Context context) {
        super(context);
        init(context);
    }

    public WaveFillingImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public WaveFillingImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @DebugLog
    private void init(Context context) {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        las = new LogAndStat("View", mSplashAnimFrames.length);
    }

    public void start() {
        isStarted = true;
        nextDrawTimeStamp = System.currentTimeMillis();
        invalidate();
    }

    @DebugLog
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // Before Layout
        if (getWidth() == 0 || getHeight() == 0)
            return;
        // Init variables
        if (!init) {
            las.logStamp("init onDraw");
            original = ImageManager.decodeSampledBitmapFromResourcewithUIL(getResources(), R.drawable.p_log_android, getWidth(), getHeight());
            result = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
            mCanvas = new Canvas(result);
            mImageViewRect = new Rect(0, 0, getWidth(), getHeight());
            init = true;
            las.logStamp("init onDraw");

        }
        // If tick reached for refresh
        if (System.currentTimeMillis() >= nextDrawTimeStamp) {
            nextDrawTimeStamp += timeTick;
            las.logStamp(index);
            Bitmap mask = ImageManager.decodeSampledBitmapFromResourcewithUIL(getResources(), getResourceForNextCycle(index), mImageViewRect.width(), mImageViewRect.height());
            mCanvas.drawBitmap(original, null, mImageViewRect, null);
            mCanvas.drawBitmap(mask, null, mImageViewRect, paint);
            canvas.drawBitmap(result, 0, 0, null);

            index++;
        }
        if (isStarted)
            // Invalidate during animation to call again on Draw
            if (index < mSplashAnimFrames.length) {
                las.logStamp("invalidate");
                invalidate();
            } else {
                las.logStats();
            }
    }

    @DebugLog
    private int getResourceForNextCycle(int index) {
        if (index < (mSplashAnimFrames.length - 1))
            index++;
        else
            index = mSplashAnimFrames.length - 1;
        return mSplashAnimFrames[index];
    }

    @DebugLog
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    }
    }

<强>结果:

  • 动画被扼杀,似乎占用的资源更少。但是它与布局动画完全不同步。需要这样做。任何最佳做法?
  • 这显然是在第一个周期花费时间的onDraw方法的初始步骤
  • 使用临时画布最终在主视图画布上绘制画布得到了很多改进