Android with surfaceview frame animation simulation results, to solve the problem OOM frame of the animation

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/Coder_Hcy/article/details/73732549

A recent project, the customer requires temporary revision, I really Zuifan this, change the background with the requirements of the main page, put on a new background, the requirement is dynamic.

Effect (I simply take five pictures do gif):



Program:

Frame animation program:

        Disadvantages: 1 seems to play only imageview frame animation 

                2. Easy OOM (broadcast thirty-four okay, broadcast over ninety, and, each OOM there are issues around 300k)

                3. See the online solution to frame animation OOM, it is a player ten, then entered, add ten, and then play. There is a problem, there is a animated pictures add ten times Caton.


surfaceview program:

         Because if the imageview to change one by one, certainly not as good as the performance surfaceview. The core should be

      canvas = surfaceHolder.lockCanvas(rect);
      canvas.drawBitmap(lruCache.get(folderName + "/" + assets[position]), null, rect, null);
        I took hundreds of pictures placed in the assets folder, and then read the image (here can do Lrucache optimization), I posted the following code:

        surfaceHolder = sv_main.getHolder();
        lruCache = new StringBitmapLruCache();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {


                rect = new Rect(0, 0, width, height);

                //获取主题
                SharedPreferences sp = getSharedPreferences("setting", Context.MODE_PRIVATE);
                String theme = sp.getString("theme", "bgone");
                switch (theme) {
                    case "bgone":
                        folderName = "bgone";
                        break;
                    case "bgtwo":
                        folderName = "bgtwo";
                        break;
                    case "bgthree":
                        folderName = "bgthree";
                        break;
                }

                try {
                    assetManager = getAssets();
                    assets = assetManager.list(folderName);
                    totalCount = assets.length;
                    if (lruCache.get(folderName + "/" + assets[0]) == null) {
                        Bitmap bitmap = BitmapFactory.decodeStream(assetManager.open(folderName + "/" + assets[0]));
                        lruCache.put(folderName + "/" + assets[0], bitmap);
                    }
                    canvas = surfaceHolder.lockCanvas(rect);
                    canvas.drawBitmap(lruCache.get(folderName + "/" + assets[0]), null, rect, null);
                    holder.unlockCanvasAndPost(canvas);

                    if (!isFlag) {
                        startDecodeThread();
                        isFlag = true;
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                }

                isFlag = true;


            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                RxUtils.unsubscribe(animationSub);
            }
        });

 private void startDecodeThread() {

        RxUtils.unsubscribe(animationSub);
        animationSub = Observable.interval(200, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io()).subscribe(new Subscriber<Long>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Long aLong) {
                Logger.i("DDSSK::" + position);
                if (position >= totalCount) {
                    position = 0;
                }

                canvas = surfaceHolder.lockCanvas(rect);
                // if (canvas != null) {

                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                if (lruCache.get(folderName + "/" + assets[position]) == null) {
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(assetManager.open(folderName + "/" + assets[position]));
                        lruCache.put(folderName + "/" + assets[position], bitmap);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                canvas.drawBitmap(lruCache.get(folderName + "/" + assets[position]), null, rect, null);
                surfaceHolder.unlockCanvasAndPost(canvas);


              /*  try {
                    Bitmap bitmap = BitmapFactory.decodeStream(assetManager.open(folderName + "/" + assets[0]));
                    canvas.drawBitmap(bitmap, null, rect, null);
                    surfaceHolder.unlockCanvasAndPost(canvas);

                } catch (IOException e) {
                    e.printStackTrace();
                }*/

                position++;
            }
        });
    }

Well, here I met to talk about the pit

1.surfaceview time to prepare, the interface is a stretch. So surfacechanged when I want to show the animation of the first graph, so as not black

2.canvas empty? Because the canvas is obtained from surfaceview if surfaceview not ready, it is absolutely empty

3. If the interface jump back, surfaceview also created, but I ordered a black screen and then bright screen, surfaceview would not be created, the animation will not be broadcast, so a switch to write, write code to trigger animations in onresume

4.surfaceview optimization, because the player a lot of pictures, take up too much resources, causing other components super card. Because surfaceview can with the new UI, so we can play in the child thread thread Carousel Figure


annex:

package utils;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

/**
 * Created by Administrator on 2017/6/23 0023.
 */

public class StringBitmapLruCache extends LruCache<String, Bitmap> {
    public StringBitmapLruCache() {
        // 构造方法传入当前应用可用最大内存的八分之一
        super((int) (Runtime.getRuntime().maxMemory() / 1024 / 8));
    }

    @Override
    // 重写sizeOf方法,并计算返回每个Bitmap对象占用的内存
    protected int sizeOf(String key, Bitmap value) {
        return value.getByteCount() / 1024;
    }

    @Override
    // 当缓存被移除时调用,第一个参数是表明缓存移除的原因,true表示被LruCache移除,false表示被主动remove移除,可不重写
    protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap
            newValue) {
        super.entryRemoved(evicted, key, oldValue, newValue);
    }

    @Override
    // 当get方法获取不到缓存的时候调用,如果需要创建自定义默认缓存,可以在这里添加逻辑,可不重写
    protected Bitmap create(String key) {
        return super.create(key);
    }
}

Conclusion: Although this requirement is fulfilled, but caused another problem, apk is too large, because the player a subject which is at least 90 chart, each 300k. I want to achieve three themes that fifty or sixty M. So I was thinking, if the original video file into something, I play the video screen, then not only solve the OOM also solve the problem of excessive APK.







Guess you like

Origin blog.csdn.net/Coder_Hcy/article/details/73732549