解決animation-list載入多張幀動畫導致OOM的問題---surfaceview用法
阿新 • • 發佈:2019-02-01
這次介面改版中有幾個介面的動畫實在酷炫,只有讓UI出一組png用幀動畫的形式展示了。心想著,這不簡單:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@mipmap/volume_00000" android:duration="100" /> <item android:drawable="@mipmap/volume_00001" android:duration="100" /> <item android:drawable="@mipmap/volume_00002" android:duration="100" /> <item android:drawable="@mipmap/volume_00003" android:duration="100" /> </animation-list>
完事~~
但是:
尼瑪啊~~~~~~~~~將近6000張圖片,我用腳趾頭想都知道用animation-list肯定直接要爆炸了。
怎麼辦,麼辦,辦?當時心情是崩潰的。
-----------------------------------------------------------------分割線-------------------------------------------------------------
聰明的大腦稍微這麼一轉 surfaceView
程式碼註釋很詳細不廢話直接貼~~
package com.meizu.speaker.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.meizu.speaker.R; /** * Created by zhangxiaotong on 2016/11/1. */ public class recycleSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{ private String TAG = this.getClass().getSimpleName(); private final SurfaceHolder mHolder; private Thread mThread; private long mFrameSpaceTime = 80; // 每幀圖片的間隔時間 private boolean mIsDraw = true; // 畫圖開關 private int mCurrentIndext = 0; // 當前正在播放的png public int mBitmapResourceIds[] = { R.mipmap.menu_00002, R.mipmap.menu_00004, R.mipmap.menu_00006, R.mipmap.menu_00008, R.mipmap.menu_00010, R.mipmap.menu_00012, R.mipmap.menu_00014, R.mipmap.menu_00016, R.mipmap.menu_00018, R.mipmap.menu_00020, R.mipmap.menu_00022, R.mipmap.menu_00024, R.mipmap.menu_00026, R.mipmap.menu_00028, R.mipmap.menu_00030, R.mipmap.menu_00032, R.mipmap.menu_00034, R.mipmap.menu_00036, R.mipmap.menu_00038, R.mipmap.menu_00040, R.mipmap.menu_00042, R.mipmap.menu_00044, R.mipmap.menu_00046, R.mipmap.menu_00048, R.mipmap.menu_00050, R.mipmap.menu_00052, R.mipmap.menu_00054, R.mipmap.menu_00056, R.mipmap.menu_00058, R.mipmap.menu_00060, R.mipmap.menu_00062, R.mipmap.menu_00064, R.mipmap.menu_00066, R.mipmap.menu_00068, R.mipmap.menu_00070, R.mipmap.menu_00072, R.mipmap.menu_00074, R.mipmap.menu_00076, R.mipmap.menu_00078, R.mipmap.menu_00080, R.mipmap.menu_00082, R.mipmap.menu_00084, R.mipmap.menu_00086, R.mipmap.menu_00088, R.mipmap.menu_00090, R.mipmap.menu_00092, R.mipmap.menu_00094, R.mipmap.menu_00096, R.mipmap.menu_00098, R.mipmap.menu_00100, R.mipmap.menu_00102, R.mipmap.menu_00104, R.mipmap.menu_00106, R.mipmap.menu_00108, R.mipmap.menu_00110, R.mipmap.menu_00112, R.mipmap.menu_00114, R.mipmap.menu_00116, R.mipmap.menu_00118, R.mipmap.menu_00120, R.mipmap.menu_00122, R.mipmap.menu_00124, R.mipmap.menu_00126, R.mipmap.menu_00128, R.mipmap.menu_00130, R.mipmap.menu_00132, R.mipmap.menu_00134, R.mipmap.menu_00136, R.mipmap.menu_00138, R.mipmap.menu_00140, R.mipmap.menu_00142, R.mipmap.menu_00144, R.mipmap.menu_00146, R.mipmap.menu_00148, R.mipmap.menu_00150, R.mipmap.menu_00152, R.mipmap.menu_00154, R.mipmap.menu_00156, R.mipmap.menu_00158, R.mipmap.menu_00160, R.mipmap.menu_00162, R.mipmap.menu_00164, R.mipmap.menu_00166, R.mipmap.menu_00168, R.mipmap.menu_00170, R.mipmap.menu_00172, R.mipmap.menu_00174, R.mipmap.menu_00176, R.mipmap.menu_00178, R.mipmap.menu_00180, R.mipmap.menu_00182, R.mipmap.menu_00184, R.mipmap.menu_00186, R.mipmap.menu_00188, R.mipmap.menu_00190, R.mipmap.menu_00000 }; private Bitmap mBitmap; public recycleSurfaceView(Context context) {this(context,null);} public recycleSurfaceView(Context context, AttributeSet attrs) {this(context,attrs,0);} public recycleSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mHolder = this.getHolder(); // 獲得surfaceholder mHolder.addCallback(this); // 添加回調,這樣三個方法才會執行 setZOrderOnTop(true); mHolder.setFormat(PixelFormat.TRANSLUCENT);// 設定背景透明 } /** 首先繼承SurfaceView,並實現SurfaceHolder.Callback介面,實現它的三個方法: surfaceCreated(SurfaceHolder holder):surface建立的時候呼叫,一般在該方法中啟動繪圖的執行緒。 surfaceChanged(SurfaceHolder holder, int format, int width,int height):surface尺寸發生改變的時候呼叫,如橫豎屏切換。 surfaceDestroyed(SurfaceHolder holder) :surface被銷燬的時候呼叫,如退出遊戲畫面,一般在該方法中停止繪圖執行緒。 還需要獲得SurfaceHolder,並添加回調函式,這樣這三個方法才會執行。 */ @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "surfaceCreated: "); if(mBitmapResourceIds == null){ Log.e(TAG, "surfaceCreated: 圖片資源為空"); return; } mThread = new Thread(this); mThread.start(); mIsDraw = true; } public void setmBitmapResourceIds(int[] mBitmapResourceIds) { this.mBitmapResourceIds = mBitmapResourceIds; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDraw = false; try { Thread.sleep(mFrameSpaceTime); Log.d(TAG, "surfaceDestroyed: Thread " + mThread.getState()); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void run() { synchronized (mHolder) { // 這裡加鎖為了以後控制這個繪製執行緒的wait與notify while (mIsDraw) { try { drawView(); Thread.sleep(mFrameSpaceTime); } catch (InterruptedException e) { e.printStackTrace(); } } } } private void drawView() { Log.i(TAG, "drawView: "); Canvas mCanvas = mHolder.lockCanvas(); // 鎖定畫布 try { mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); // 清除螢幕 mCanvas.drawColor(Color.BLACK); mBitmap = BitmapFactory.decodeResource(getResources(), mBitmapResourceIds[mCurrentIndext]); mCanvas.drawBitmap(mBitmap, 0, 0, null); if (mCurrentIndext == mBitmapResourceIds.length - 1) { mCurrentIndext = 0; } } catch (Exception e) { e.printStackTrace(); } finally { mCurrentIndext++; if (mCanvas != null) { mHolder.unlockCanvasAndPost(mCanvas); // 提交畫布 } recycle(mBitmap); // 這裡回收資源非常重要! } } private void recycle(Bitmap mBitmap) { if(mBitmap != null) mBitmap.recycle(); } } 佈局檔案: <com.meizu.speaker.view.recycleSurfaceView android:id="@+id/anim" android:layout_width="@dimen/common_margin_31" android:layout_height="@dimen/common_margin_240" android:layout_centerVertical="true" android:layout_marginStart="@dimen/common_margin_60" android:scaleType="fitXY"/> 預覽~~