使用单个AsyncTask(后台线程)来编码性能

时间:2015-04-28 12:28:42

标签: android multithreading android-asynctask

  

代码运行得非常好。但它很慢,有时显示ANR。我想要一个单独的线程或连续运行的AsyncTask并处理imagebrightness值。我无法创建多个AsyncTask,因为(它们都执行相同的操作)。

我只需要获取YUV byte codeconvert it to bitmap并将其设置为我的Activity View

private android.hardware.Camera.PreviewCallback previewCallback = new android.hardware.Camera.PreviewCallback()
    {
        public void onPreviewFrame(final byte abyte0[] , Camera camera)
        {       
            int[] rgbData =  YuvUtils.myDecodeGreyscale(abyteData, widthPreview, heightPreview, imageBrightness, nonGreencolorOffset, greenColorOffset); 

            editedBitmap.setPixels(rgbData, 0, widthPreview, 0, 0, widthPreview, heightPreview);

            if(MainActivity2.cameraId==CameraInfo.CAMERA_FACING_FRONT)
            {   
                matrix.setRotate(270F);
            }
            finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);

            //above all methods should be call on background Thread.
            MainActivity2.drawView.setBitmapToDraw(finalBitmap);//only this statement should be use in Main Thread
        }
    };

我尝试了什么

我在每个previewFrame()调用上创建了一个新的AsyncTask。它挂起了设备。我也尝试过使用Thread但是遇到同样的问题。

我只是希望我的代码在单独的后台线程上执行,该线程与我的Activity绑定服务。 我也是Thread.sleep来克服ANR。但它会停止用户界面。

try
{
   Thread.sleep(1L);

}
catch (InterruptedException interruptedexception)
{
    interruptedexception.printStackTrace();
}
  

onPreviewFrame会在一秒钟内调用三次。我想在几秒钟内完成一到两次操作以显示连续的CameraPreview。 someOne能否告诉我如何实现这一目标。

我的想法是什么。

  1. 我应该每次睡眠半秒钟,因为我没有 想要在一秒钟内设置三次预览。
  2. 我应该使用静态变量或创建内部AsyncTask来处理 这些操作。
  3. 的AsyncTask

    public class CameraPreviewTask extends AsyncTask<Void, Void, Void>
    {
        public static int cameraId;
        public static boolean isRunning;
        public Context ctx;
        public byte[] data;
        public boolean dataAvailable;
        private Bitmap editedBitmap;
        private Bitmap finalBitmap;
        private int green;
        public double greenColorOffset;
        private int heightPreview;
        private int widthPreview;
        public int imageBrightness=70;
        private int iterator;
        private int iteratorLimit;
        int j;
        private Matrix matrix;
        public double nonGreencolorOffset=30;
        private int nongreen=20;
        private int p;
        private int[] pixels_preview;
        public boolean saveCurrentFrame;
        public boolean workingOnData;
    
        public CameraPreviewTask(final Context ctx, final int widthPreview, final int heightPreview)
        {
            saveCurrentFrame = false;
            dataAvailable = false;
            workingOnData = false;
            this.ctx = ctx;
            this.widthPreview = widthPreview;
            this.heightPreview = heightPreview;
            iteratorLimit = widthPreview * heightPreview;
            pixels_preview = new int[iteratorLimit];
            editedBitmap = Bitmap.createBitmap(widthPreview, heightPreview, Config.ARGB_8888);
            (matrix = new Matrix()).postRotate(90.0f);
            CameraPreviewTask.isRunning = true;
        }
    
        protected Void doInBackground(final Void... array) 
        {
            while (CameraPreviewTask.isRunning) 
            {
                try 
                {
                    while (!dataAvailable) 
                    {
                        Thread.sleep(1L);
                    }
                }
                catch (InterruptedException ex) 
                {
                    Log.e("EditorWorker", "Error while waiting for data =" + ex.getMessage());
                }
    
                try 
                {
                    workingOnData = true;
    
                    int[] rgbData =  YuvUtils.myDecodeGreyscale(data, widthPreview, heightPreview, imageBrightness, nonGreencolorOffset, greenColorOffset); 
    
                    editedBitmap.setPixels(rgbData, 0, widthPreview, 0, 0, widthPreview, heightPreview);
    
                    if(MainActivity2.cameraId==CameraInfo.CAMERA_FACING_FRONT)
                    {   
                        matrix.setRotate(270F);
                    }
    
                    finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);
    
                    publishProgress((Void[])new Void[0]);
    
                    workingOnData = false;
                }
                catch (Exception ex2) 
                {
                    Log.e("Error", ex2.getMessage() + "");
                }
                finally 
                {
                    workingOnData = false;
                }
            }
            return null;
        }
    
        protected void onProgressUpdate(Void... array) 
        {
            super.onProgressUpdate((Void[])array);
    
            MainActivity2.drawView.setBitmapToDraw(finalBitmap);
    
            if (saveCurrentFrame) 
            {
                saveCurrentFrame = false;
    
                new BitmapSaver(ctx, finalBitmap).start();
            }
        }
    
        @TargetApi(11)
        public void start()
        {
            if (Build.VERSION.SDK_INT >= 11)
            {
                executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Void[0]);
            }
            else
            {
                execute(new Void[0]);
            }
    
        }
    }
    

1 个答案:

答案 0 :(得分:0)

我有一个可能以不同方式重新启动的想法,如果我在某处创建了可怕的内存泄漏或完全忽略线程安全,请有人纠正我。我总是指望只由一个线程写的变量。

在你的MainActivity中,制作一个Handler / Runnable组合,让它每次更新你的视图...... 40ms:

MainActivity extends Activity{ //beware pseudo code
    Bitmap finalBitmap;
    Handler viewHandler; //android.os.Handler, not the java one
    boolean camIsRunning = false;
    AtomicBoolean newBitmap = false;
    Camera myCamera;
    byte aByte[];

    Runnable updateView = new Runnable(){
        @Override
        public void run(){
            if(camIsRunning){
                drawView.setBitmapToDraw(finalBitmap);
                alsoUpdateSeekbarAndStuffIMayHaveForgotten(); //<- edit
                viewHandler.postDelayed(updateView, 40);
            }
        }
    };

    onCreate(...){ //beware pdeudo code again
        initYourStuff(); //whatever
        viewHandler = new Handler();
        finalBitmap = initBitmap(); //not sure how you initialize/start your bitmap handling, just make sure to draw your bitmap only after there is one, so put a placeholder here until the cam is running.
        startCamera(); //also triggers camIsRunning;
        //After there is a bitmap and the camera is running  and actually every time you start up your camera:
        viewHandler.post(updateView);
        new BitmapOperator().start();
    }

    class BitmapOperator extends Thread{
        public void run(){
            while(camIsRunning){
                if(newBitmap.weakCompareAndSet(true, false)) //if there is a new bitmap, reset to false and process.
                    processBitmap(aByte[], camera); //convert here
            }
        }
    }
private android.hardware.Camera.PreviewCallback previewCallback = new android.hardware.Camera.PreviewCallback()
{
    public void onPreviewFrame(final byte abyte0[] , Camera camera)
    {       
        aByte[] = abyte0[];
        myCamera = camera;
        newBitmap.set(true); //Atomic for thread safety because I'm too lazy to sync stuff manually for just this one variable.
    }
};
}