AsyncTask 应用程序仍然运行缓慢

发布于 2024-11-14 19:19:09 字数 15041 浏览 2 评论 0原文

我有一个可以在位图上添加效果的应用程序。当用户滑动滑动条时,效果的失真程度会增加/减少,然后重新绘制位图。我的自定义视图类称为 TouchView,该类获取位图并调用 Filters 类中处理图像的方法。我曾帮助实现 asyncTask 来加快处理速度,但无济于事。 AsyncTask 是否正确实现。谢谢马特。

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);



     //.....code that gets the bitmap from camera and sdcard

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());


      // instantiate the image processing class
      f = new Filters();





    }// end of touchView constructor


    public void findCirclePixels(){ 



        //set level of distortion
        float prog = (float)Progress/150000;

        // call processing method on bitmap
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()





    }//end of onTouchEvent





    public void initSlider(final HorizontalSlider slider)
    {
        Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            Log.e(TAG, "***********progress = "+Progress);

        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {

            }

            @Override
            protected Void doInBackground(Void... params) {
              TouchView.this.findCirclePixels();
              return null;

            }

            protected void onPostExecute(Void result) {                               
              TouchView.this.invalidate();
            }
        }




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);




    }//end of onDraw




    protected void setProgress(int progress2) {
        this.Progress = progress2;
        new MyTask().execute();


    }




}

[更新] 这就是我现在所拥有的。不幸的是,该应用程序现在运行速度变慢。你还有什么我可以尝试的想法吗?

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;
    private MyTask mt = null;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);




        tempFile = new File(Environment.getExternalStorageDirectory().
                getAbsolutePath() + "/"+"image.jpg");

        imageArray = new byte[(int)tempFile.length()];


     try{

            InputStream is = new FileInputStream(tempFile);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);


            int i = 0;

            while (dis.available() > 0) {
            imageArray[i] = dis.readByte();
            i++;
            }

            dis.close();

       } catch (Exception e) {

               e.printStackTrace();
            }



        BitmapFactory.Options bfo = new BitmapFactory.Options();
        bfo.inSampleSize = 1;

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());



      f = new Filters();




    }// end of touchView constructor


    public void findCirclePixels(){ 




        float prog = (float)Progress/150000;
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()









    public void initSlider(final HorizontalSlider slider)
    {
        Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            Log.e(TAG, "***********progress = "+Progress);

        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {

            }

            @Override
            protected Void doInBackground(Void... params) {
              TouchView.this.findCirclePixels();

              return null;

            }

            protected void onPostExecute(Void result) { 

                while(!isCancelled()){
              TouchView.this.invalidate();
                }
                     mt.cancel(true);
            }
        }




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);
        canvas.drawCircle(centreX, centreY, radius,pTouch);



    }//end of onDraw




    protected void setProgress(int progress2) {
        this.Progress = progress2;


        mt = new MyTask();
        mt.execute();
        AsyncRunning = true;


    }




}

[更新2]

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ProgressBar;

public class HorizontalSlider extends ProgressBar {



    private OnProgressChangeListener listener;

    private static int padding = 2;

    public interface OnProgressChangeListener {
        void onProgressChanged(View v, int progress);
    }

    /*
    public HorizontalSlider(Context context, AttributeSet attrs,

                            Map inflateParams, int defStyle) {

                    super(context, attrs, inflateParams, defStyle);

            }



            public HorizontalSlider(Context context, AttributeSet attrs,

                            Map inflateParams) {

                    super(context, attrs, inflateParams, android.R.attr.progressBarStyleHorizontal);
}*/
    public HorizontalSlider(Context context) {
        super(context);

    }
    public HorizontalSlider(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }


    public void setOnProgressChangeListener(OnProgressChangeListener l) {
        listener = l;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();

        if (action == MotionEvent.ACTION_DOWN
                || action == MotionEvent.ACTION_MOVE) {
            float x_mouse = event.getX() - padding;
            float width = getWidth() - 2*padding;
            int progress = Math.round((float) getMax() * (x_mouse / width));

            if (progress < 0)
                progress = 0;

            this.setProgress(progress);

            if (listener != null)
                listener.onProgressChanged(this, progress);

        }

        return true;
    }
}

[更新3]

嗨,好的,我已经将我的代码更改为您的修正,并更改了几行,以便通过添加 TouchView.this.invalidate() 等来更新视图。关于horizo​​ntalSlider 我已将其设置为在设置进度时仅检查 ACTION_UP。这样,用户可以移动滑动条,但只有当用户释放滑动条时视图才会失效。我有点希望位图能够随着条的移动而实时更新,但是图像处理类“过滤器”需要大约 20 秒来处理位图,这不太好。我认为我需要研究后者,因为我确信您应该能够比这更快地处理位图!:)。如果这与 AsyncTask 一样快,那么我可能必须考虑首先绘制不失真的相机位图,然后创建另一个仅存在圆形效果的位图叠加层。这样过滤器 cod 可能只有 1/3 的像素可以循环?我将发布代码以确保这是您所建议的方式。

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import com.tecmark.HorizontalSlider.OnProgressChangeListener;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff.Mode;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;
    private MyTask mt = null;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);




        tempFile = new File(Environment.getExternalStorageDirectory().
                getAbsolutePath() + "/"+"image.jpg");

        imageArray = new byte[(int)tempFile.length()];


     try{

            InputStream is = new FileInputStream(tempFile);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);


            int i = 0;

            while (dis.available() > 0) {
            imageArray[i] = dis.readByte();
            i++;
            }

            dis.close();

       } catch (Exception e) {

               e.printStackTrace();
            }



        BitmapFactory.Options bfo = new BitmapFactory.Options();
        bfo.inSampleSize = 1;

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());



       f = new Filters();


        pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
        pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
        pTouch.setColor(Color.TRANSPARENT);
        pTouch.setStyle(Paint.Style.STROKE);


    }// end of touchView constructor


    public void findCirclePixels(){ 




        float prog = (float)Progress/150000;
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()







    public void initSlider(final HorizontalSlider slider)
    {
      //  Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            //TouchView.this.Progress = progress;

              if (mt != null) {
                mt.cancel(true);
              }

              mt = new MyTask();
              mt.execute();


        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {
            //  Log.e(TAG, "***********in PREEXECUTE");
            }

            @Override
            protected Void doInBackground(Void... params) {
            //  Log.e(TAG, "***********in DOINBACKGROUND");
                if(!mt.isCancelled()){
            //  Log.e(TAG, "***********in doInBackgroud about to call fcp()");
            //  Log.e(TAG, "***********in doinbackground asyncStatus = "+mt.getStatus());
              TouchView.this.findCirclePixels();
              Log.e(TAG, "***********in doinbackground fcp() called!!!!");
                }

              return null;

            }

            protected void onPostExecute(Void result) { 
            //  Log.e(TAG, "***********in POSTEXECUTE");
                if(!isCancelled()){
           // Log.e(TAG, "***********in postExecute task not canclled and about to invalidate");
          //  Log.e(TAG, "***********in postexecute asyncStatus = "+mt.getStatus());
              TouchView.this.invalidate();
          //    Log.e(TAG, "***********in postexecute  invalidate() called!!!!");
           //   Log.e(TAG, "***********in postexecute asyncStatus = "+mt.getStatus());
                }


            }



        }// end of mytask




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);
        canvas.drawCircle(centreX, centreY, radius,pTouch);



    }//end of onDraw




    protected void setProgress(int progress2) {
        //Log.e(TAG, "***********in SETPROGRESS");
        this.Progress = progress2;

        //Log.e(TAG, "***********in setprogress progress = "+Progress);

        //Log.e(TAG, "***********in setProgress about to create mytask ");
        mt = new MyTask();
        //Log.e(TAG, "***********in setprogress about to execute mytask");
        //Log.e(TAG, "***********in setprogress asyncStatus = "+mt.getStatus());
        mt.execute();
    //  Log.e(TAG, "***********in setprogress asyncStatus = "+mt.getStatus());
    //  Log.e(TAG, "***********in setprogress mytask executed!!!!! ");



    }




}

@Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();

        if (action == MotionEvent.ACTION_UP
                /*|| action == MotionEvent.ACTION_MOVE*/) {
            float x_mouse = event.getX() - padding;
            float width = getWidth() - 2*padding;

             int progress = Math.round((float) getMax() * (x_mouse / width));

            if (progress < 0)
                progress = 0;

            this.setProgress(progress);

            if (listener != null)
                listener.onProgressChanged(this, progress);
        }


        return true;
    }
}

I've an app that places an effect on a bitmap. When the user slides the slidebar the level of distortion of the efect increases/decreases and the bitmap is then redrawn. My custom view class is called TouchView and this class gets the bitmap and calls a method from the Filters class that processes the image. I've had help implementing asyncTask to speed the processing up but to no avail. Is AsyncTask implemented properly. Thanks Matt.

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);



     //.....code that gets the bitmap from camera and sdcard

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());


      // instantiate the image processing class
      f = new Filters();





    }// end of touchView constructor


    public void findCirclePixels(){ 



        //set level of distortion
        float prog = (float)Progress/150000;

        // call processing method on bitmap
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()





    }//end of onTouchEvent





    public void initSlider(final HorizontalSlider slider)
    {
        Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            Log.e(TAG, "***********progress = "+Progress);

        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {

            }

            @Override
            protected Void doInBackground(Void... params) {
              TouchView.this.findCirclePixels();
              return null;

            }

            protected void onPostExecute(Void result) {                               
              TouchView.this.invalidate();
            }
        }




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);




    }//end of onDraw




    protected void setProgress(int progress2) {
        this.Progress = progress2;
        new MyTask().execute();


    }




}

.

[update]
This is what i've got now. The app is running slower now unfortunately. Have you any further ideas that i could try?

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;
    private MyTask mt = null;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);




        tempFile = new File(Environment.getExternalStorageDirectory().
                getAbsolutePath() + "/"+"image.jpg");

        imageArray = new byte[(int)tempFile.length()];


     try{

            InputStream is = new FileInputStream(tempFile);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);


            int i = 0;

            while (dis.available() > 0) {
            imageArray[i] = dis.readByte();
            i++;
            }

            dis.close();

       } catch (Exception e) {

               e.printStackTrace();
            }



        BitmapFactory.Options bfo = new BitmapFactory.Options();
        bfo.inSampleSize = 1;

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());



      f = new Filters();




    }// end of touchView constructor


    public void findCirclePixels(){ 




        float prog = (float)Progress/150000;
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()









    public void initSlider(final HorizontalSlider slider)
    {
        Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            Log.e(TAG, "***********progress = "+Progress);

        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {

            }

            @Override
            protected Void doInBackground(Void... params) {
              TouchView.this.findCirclePixels();

              return null;

            }

            protected void onPostExecute(Void result) { 

                while(!isCancelled()){
              TouchView.this.invalidate();
                }
                     mt.cancel(true);
            }
        }




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);
        canvas.drawCircle(centreX, centreY, radius,pTouch);



    }//end of onDraw




    protected void setProgress(int progress2) {
        this.Progress = progress2;


        mt = new MyTask();
        mt.execute();
        AsyncRunning = true;


    }




}

.

[update 2]

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ProgressBar;

public class HorizontalSlider extends ProgressBar {



    private OnProgressChangeListener listener;

    private static int padding = 2;

    public interface OnProgressChangeListener {
        void onProgressChanged(View v, int progress);
    }

    /*
    public HorizontalSlider(Context context, AttributeSet attrs,

                            Map inflateParams, int defStyle) {

                    super(context, attrs, inflateParams, defStyle);

            }



            public HorizontalSlider(Context context, AttributeSet attrs,

                            Map inflateParams) {

                    super(context, attrs, inflateParams, android.R.attr.progressBarStyleHorizontal);
}*/
    public HorizontalSlider(Context context) {
        super(context);

    }
    public HorizontalSlider(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }


    public void setOnProgressChangeListener(OnProgressChangeListener l) {
        listener = l;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();

        if (action == MotionEvent.ACTION_DOWN
                || action == MotionEvent.ACTION_MOVE) {
            float x_mouse = event.getX() - padding;
            float width = getWidth() - 2*padding;
            int progress = Math.round((float) getMax() * (x_mouse / width));

            if (progress < 0)
                progress = 0;

            this.setProgress(progress);

            if (listener != null)
                listener.onProgressChanged(this, progress);

        }

        return true;
    }
}

.

[update 3]

Hi, ok i've changed my code to your amendements and changed i couple of lines so the view is updated by adding TouchView.this.invalidate() etc. Regarding the the horizontalSlider i've set it to check for only ACTION_UP when setting the progress. This way the user can move the slidebar but the view is only invalidated when the user releases the slidebar. i kinda hoped that the bitmap would be updated in real-time as the bar is moved, but the image processing class 'Filters' takes about 20 seconds to process a bitmap which is no good. i think i need to work on the latter as i'm sure you should be able to process a bitmap faster than that!:). If this is as fast as AsyncTask can go then i might have to think about drawing the camera bitmap first with no distortion, then create another bitmap overlay where only the circle effect is present. this way the filter cod only has maybe 1/3 of the pixels to loop through? i'll post the code to make sure that it's how you've suggested.

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import com.tecmark.HorizontalSlider.OnProgressChangeListener;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff.Mode;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class TouchView extends View{


    private File tempFile;
    private byte[] imageArray;
    private Bitmap bgr;
    private Bitmap bm;
    private Bitmap bgr2 = null;;
    private Paint pTouch;
    private int centreX = 1;
    private int centreY = 1;
    private int radius = 50;
    private int Progress = 1;
    private static final String TAG = "*********TouchView";
    private Filters f = null;
    private boolean AsyncRunning = false;
    private MyTask mt = null;



    public TouchView(Context context) {
        super(context);
       // TouchView(context, null);
    }




    public TouchView(Context context, AttributeSet attr) {
        super(context,attr);




        tempFile = new File(Environment.getExternalStorageDirectory().
                getAbsolutePath() + "/"+"image.jpg");

        imageArray = new byte[(int)tempFile.length()];


     try{

            InputStream is = new FileInputStream(tempFile);
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);


            int i = 0;

            while (dis.available() > 0) {
            imageArray[i] = dis.readByte();
            i++;
            }

            dis.close();

       } catch (Exception e) {

               e.printStackTrace();
            }



        BitmapFactory.Options bfo = new BitmapFactory.Options();
        bfo.inSampleSize = 1;

        bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
        bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
        bgr = bm.copy(bm.getConfig(), true);
        bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());



       f = new Filters();


        pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
        pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
        pTouch.setColor(Color.TRANSPARENT);
        pTouch.setStyle(Paint.Style.STROKE);


    }// end of touchView constructor


    public void findCirclePixels(){ 




        float prog = (float)Progress/150000;
        bgr2 = f.barrel(bgr,prog);


        }// end of changePixel()







    public void initSlider(final HorizontalSlider slider)
    {
      //  Log.e(TAG, "******setting up slider*********** ");
        slider.setOnProgressChangeListener(changeListener);
    }



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() {


        @Override
        public void onProgressChanged(View v, int progress) {
            // TODO Auto-generated method stub

            setProgress(progress);

            //TouchView.this.Progress = progress;

              if (mt != null) {
                mt.cancel(true);
              }

              mt = new MyTask();
              mt.execute();


        }
    };

    private class MyTask extends AsyncTask<Void, Void, Void> {
          protected void onPreExecute() {
            //  Log.e(TAG, "***********in PREEXECUTE");
            }

            @Override
            protected Void doInBackground(Void... params) {
            //  Log.e(TAG, "***********in DOINBACKGROUND");
                if(!mt.isCancelled()){
            //  Log.e(TAG, "***********in doInBackgroud about to call fcp()");
            //  Log.e(TAG, "***********in doinbackground asyncStatus = "+mt.getStatus());
              TouchView.this.findCirclePixels();
              Log.e(TAG, "***********in doinbackground fcp() called!!!!");
                }

              return null;

            }

            protected void onPostExecute(Void result) { 
            //  Log.e(TAG, "***********in POSTEXECUTE");
                if(!isCancelled()){
           // Log.e(TAG, "***********in postExecute task not canclled and about to invalidate");
          //  Log.e(TAG, "***********in postexecute asyncStatus = "+mt.getStatus());
              TouchView.this.invalidate();
          //    Log.e(TAG, "***********in postexecute  invalidate() called!!!!");
           //   Log.e(TAG, "***********in postexecute asyncStatus = "+mt.getStatus());
                }


            }



        }// end of mytask




    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);


        canvas.drawBitmap(bgr2, 0, 0, null);
        canvas.drawCircle(centreX, centreY, radius,pTouch);



    }//end of onDraw




    protected void setProgress(int progress2) {
        //Log.e(TAG, "***********in SETPROGRESS");
        this.Progress = progress2;

        //Log.e(TAG, "***********in setprogress progress = "+Progress);

        //Log.e(TAG, "***********in setProgress about to create mytask ");
        mt = new MyTask();
        //Log.e(TAG, "***********in setprogress about to execute mytask");
        //Log.e(TAG, "***********in setprogress asyncStatus = "+mt.getStatus());
        mt.execute();
    //  Log.e(TAG, "***********in setprogress asyncStatus = "+mt.getStatus());
    //  Log.e(TAG, "***********in setprogress mytask executed!!!!! ");



    }




}

.

@Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();

        if (action == MotionEvent.ACTION_UP
                /*|| action == MotionEvent.ACTION_MOVE*/) {
            float x_mouse = event.getX() - padding;
            float width = getWidth() - 2*padding;

             int progress = Math.round((float) getMax() * (x_mouse / width));

            if (progress < 0)
                progress = 0;

            this.setProgress(progress);

            if (listener != null)
                listener.onProgressChanged(this, progress);
        }


        return true;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无畏 2024-11-21 19:19:09

看起来,对于滑块中的每个值更改,您都在创建 MyTask 并运行它。相反,可能表现更好的一件事是仅在释放滑块(停止移动)时更新侦听器。看起来 Horizo​​ntalSlider 是一个自定义类,所以我无法说出其中发生的情况。

如果滑块从左向右移动,则在移动过程中可能会触发更新事件 100 次。那将是 100 个后台任务!

更新

一种可能是在生成另一个任务之前cancel() 活动的MyTask。如果您采用该路线,则需要在 onPostExecute 中调用 isCancelled(),并且只有在任务取消时才使视图无效。但是,如果 findCirclePixels() 中的代码是瓶颈,则此方法将不起作用。我的猜测是,在创建新任务之前取消活动任务将不能解决您的问题。

正确编码(仅在必要时创建 MyTask)仍然是最佳途径。考虑一下,对于每个 AsyncTask,操作系统都必须生成一个新的后台线程,这会带来自己的开销。不要被 doInBackground() 中放入的少量代码所迷惑。

再次更新

我已经清理了您的代码并添加了建议评论:

public class TouchView extends View{

  private File tempFile;
  private byte[] imageArray;
  private Bitmap bgr;
  private Bitmap bm;
  private Bitmap bgr2 = null;;
  private Paint pTouch;
  private int centreX = 1;
  private int centreY = 1;
  private int radius = 50;
  private int Progress = 1;
  private static final String TAG = "*********TouchView";
  private Filters f = null;
  private MyTask mt = null;

  public TouchView(Context context) {
    super(context);
  }

  public TouchView(Context context, AttributeSet attr) {
    super(context,attr);

    tempFile = new File(Environment.getExternalStorageDirectory().
            getAbsolutePath() + "/"+"image.jpg");
    imageArray = new byte[(int) tempFile.length()];

    try{
      InputStream is = new FileInputStream(tempFile);
      BufferedInputStream bis = new BufferedInputStream(is);
      DataInputStream dis = new DataInputStream(bis);

      int i = 0;
      while (dis.available() > 0) {
        imageArray[i] = dis.readByte();
        i++;
      }

      dis.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

    BitmapFactory.Options bfo = new BitmapFactory.Options();
    bfo.inSampleSize = 1;

    bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
    bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
    bgr = bm.copy(bm.getConfig(), true);
    bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
    f = new Filters();
  }

  public void findCirclePixels(){ 
    float prog = (float) Progress / 150000;
    bgr2 = f.barrel(bgr, prog);
  }

  public void initSlider(final HorizontalSlider slider) {
    slider.setOnProgressChangeListener(changeListener);
  }

  private OnProgressChangeListener changeListener = new OnProgressChangeListener() {
    @Override
    public void onProgressChanged(View v, int progress) {
      /*
      TODO: If there is a way to see if the slider is still being changed (control
      has not been released), then you should return and not continue with the
      creation of another task
      */

      this.Progress = progress2;

      if (mt != null) {
        mt.cancel();
      }

      mt = new MyTask();
      mt.execute();
    }
  };

  private class MyTask extends AsyncTask<Void, Void, Void> {
      protected void onPreExecute() {
      }

      @Override
      protected Void doInBackground(Void... params) {
        // This check is not necessary if coded properly
        if (!isCancelled()) {
          TouchView.this.findCirclePixels();
        }
        return null;
      }

      protected void onPostExecute(Void result) { 
        // This check is not necessary if coded properly
        if (!isCancelled()) {
          TouchView.this.invalidate();
        }
      }
  }




  @Override
  public void onDraw(Canvas canvas){
    super.onDraw(canvas);

    canvas.drawBitmap(bgr2, 0, 0, null);
    canvas.drawCircle(centreX, centreY, radius, pTouch);
  }
}

It appears that for every value change in your slider, you are creating your MyTask and running it. Instead, one thing that might perform better is only updating your listener when the slider has been released (stopped moving). It looks like HorizontalSlider is a custom class, so I can't speak for what is happening in there.

If a slider is being moved from left to right, it may fire off update events 100 times during that move. That would be 100 background tasks!

UPDATE

One possibility would be to cancel() your active MyTask before you produce another one. If you take that route you need to call isCancelled() in onPostExecute and only invalidate your view if the task is not cancelled. However, if the code in findCirclePixels() is the bottleneck, this will not work. My guess is that cancelling the active task before creating a new one will NOT solve your problem.

Coding this up properly (only creating your MyTask when necessary) is still going to be the best route. Consider that for every AsyncTask the OS has to spawn a new background thread, which comes with its own overhead. Don't be fooled by the small amount of code you have put in doInBackground().

UPDATE AGAIN

I have cleaned up your code and added comments for suggestion:

public class TouchView extends View{

  private File tempFile;
  private byte[] imageArray;
  private Bitmap bgr;
  private Bitmap bm;
  private Bitmap bgr2 = null;;
  private Paint pTouch;
  private int centreX = 1;
  private int centreY = 1;
  private int radius = 50;
  private int Progress = 1;
  private static final String TAG = "*********TouchView";
  private Filters f = null;
  private MyTask mt = null;

  public TouchView(Context context) {
    super(context);
  }

  public TouchView(Context context, AttributeSet attr) {
    super(context,attr);

    tempFile = new File(Environment.getExternalStorageDirectory().
            getAbsolutePath() + "/"+"image.jpg");
    imageArray = new byte[(int) tempFile.length()];

    try{
      InputStream is = new FileInputStream(tempFile);
      BufferedInputStream bis = new BufferedInputStream(is);
      DataInputStream dis = new DataInputStream(bis);

      int i = 0;
      while (dis.available() > 0) {
        imageArray[i] = dis.readByte();
        i++;
      }

      dis.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

    BitmapFactory.Options bfo = new BitmapFactory.Options();
    bfo.inSampleSize = 1;

    bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
    bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
    bgr = bm.copy(bm.getConfig(), true);
    bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
    f = new Filters();
  }

  public void findCirclePixels(){ 
    float prog = (float) Progress / 150000;
    bgr2 = f.barrel(bgr, prog);
  }

  public void initSlider(final HorizontalSlider slider) {
    slider.setOnProgressChangeListener(changeListener);
  }

  private OnProgressChangeListener changeListener = new OnProgressChangeListener() {
    @Override
    public void onProgressChanged(View v, int progress) {
      /*
      TODO: If there is a way to see if the slider is still being changed (control
      has not been released), then you should return and not continue with the
      creation of another task
      */

      this.Progress = progress2;

      if (mt != null) {
        mt.cancel();
      }

      mt = new MyTask();
      mt.execute();
    }
  };

  private class MyTask extends AsyncTask<Void, Void, Void> {
      protected void onPreExecute() {
      }

      @Override
      protected Void doInBackground(Void... params) {
        // This check is not necessary if coded properly
        if (!isCancelled()) {
          TouchView.this.findCirclePixels();
        }
        return null;
      }

      protected void onPostExecute(Void result) { 
        // This check is not necessary if coded properly
        if (!isCancelled()) {
          TouchView.this.invalidate();
        }
      }
  }




  @Override
  public void onDraw(Canvas canvas){
    super.onDraw(canvas);

    canvas.drawBitmap(bgr2, 0, 0, null);
    canvas.drawCircle(centreX, centreY, radius, pTouch);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文