实现AsyncTask的提示 [英] tips for implementing AsyncTask

查看:127
本文介绍了实现AsyncTask的提示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好我有一个应用程序,放在一个圆上bitmapa和滑杆改变的圆圈内的像素的RGB值。我想使用的AsyncTask加快改变的像素的过程。我不知道从哪里开始。我已经注释掉了一些code在活动文件的底部,因为这是我第一次attept吧:)。任何人都可以点我在正确的方向,如何实现这一点。该活动调用自定义视图(的TouchView),因为我了解的AsyncTask必须在UI线程实例化。我在想在preExecute()初始化滑杆等的,但不知道如何把所有的工人东西在doInBackground()。任何帮助将AP preciated,感谢马特。

 公共类Jjilapp延伸活动{


    私人按钮B1;

    私有静态最后字符串变量=********* jjil;


    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        Log.e(TAG,***********里面的O​​nCreate有关设置内容查看=);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow()。setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        的setContentView(R.layout.touchview);
        最后的TouchView的TouchView =(的TouchView)findViewById(R.id.touchview);
        最终水平滑滑块=(水平)findViewById(R.id.slider);

        touchView.initSlider(滑盖);


        B1 =(按钮)findViewById(R.id.button1);
        b1.setOnClickListener(新OnClickListener(){

            @覆盖
            公共无效的onClick(视图v){
                Log.e(TAG,onClickButton1);

            }
        });



    在OnCreate的} //结束

   / *私有类UpdateCirclePixels扩展的AsyncTask<整数,整数,整数GT; {

        @覆盖
        在preExecute保护无效(){
            最后的TouchView的TouchView =(的TouchView)findViewById(R.id.touchview);
            最终水平滑滑块=(水平)findViewById(R.id.slider);

            touchView.initSlider(滑盖);

        }



        @覆盖
        保护整数doInBackground(整数...为arg0){
            // TODO自动生成方法存根

            publishProgress(进度);
            返回null;
        }

        @覆盖
        保护无效onProgressUpdate(整数...进度){


        }


    的AsyncTask的} //结束* /


jjilapp的} //结束
 

 公共类的TouchView扩展视图{


    私人文件临时文件;
    私人字节[] imageArray;
    私人位图BGR;
    私人位图BM;
    私人油漆pTouch;
    私人诠释CENTREX = 1;
    私人诠释centreY = 1;
    私人诠释半径= 50;
    私人诠释进展情况;
    私有静态最后字符串变量=*********的TouchView;




    公众的TouchView(上下文的背景下){
        超(上下文);
       //的TouchView(背景下,NULL);
    }




    公众的TouchView(上下文的背景下,的AttributeSet attr)使用{
        超(背景下,ATTR);




        临时文件=新的文件(Environment.getExternalStorageDirectory()。
                getAbsolutePath()+/"+"image.jpg);

        imageArray =新的字节[(INT)tempFile.length()];


     尝试{

            InputStream的是=新的FileInputStream(临时文件);
            的BufferedInputStream双=新的BufferedInputStream(是);
            的DataInputStream解散=新的DataInputStream(之二);


            INT I = 0;

            而(dis.available()大于0){
            imageArray [I] = dis.readByte();
            我++;
            }

            透露();

       }赶上(例外五){

               e.printStackTrace();
            }



        BitmapFactory.Options BFO =新BitmapFactory.Options();
        bfo.inSampleSize = 1;

        BM = BitmapFactory.de codeByteArray(imageArray,0,imageArray.length,BFO);
        BGR = Bitmap.createBitmap(bm.getWidth(),bm.getHeight(),bm.getConfig());
        BGR = bm.copy(bm.getConfig(),TRUE);



        pTouch =新的油漆(Paint.ANTI_ALIAS_FLAG);
        pTouch.setXfermode(新PorterDuffXfermode(Mode.SRC_OUT));
        pTouch.setColor(Color.TRANSPARENT);
        pTouch.setStyle(Paint.Style.STROKE);


        //pTouch.setMaskFilter(new BlurMaskFilter(15,Blur.NORMAL));



    } //的TouchView构造结束


    公共无效findCirclePixels(){



        的for(int i = CENTREX-50; I< CENTREX + 50; ++ I){
            对于(INT Y = centreY-50; Y< centreY + 50; + Y){

    如果(的Math.sqrt(Math.pow(ⅰ -  CENTREX,2)+(Mat​​h.pow(γ -  centreY,2)))≤; =半径){

                    bgr.setPixel(I,Y,Color.rgb(进度+ 50,进步,进步+ 100));
                }
            }
        }

        changePixel的} //结束()




    @覆盖
    公共布尔的onTouchEvent(MotionEvent EV){

        开关(ev.getAction()){

            案例MotionEvent.ACTION_DOWN:{

                CENTREX =(INT)ev.getX();
                centreY =(int)的ev.getY();
                findCirclePixels();
                无效();

                打破;
            }

            案例MotionEvent.ACTION_MOVE:{

                    CENTREX =(INT)ev.getX();
                    centreY =(int)的ev.getY();
                    findCirclePixels();
                    无效();
                    打破;

            }

            案例MotionEvent.ACTION_UP:

                打破;

        }
        返回true;
    } //的onTouchEvent结束





    公共无效initSlider(最终水平滑滑块)
    {
        Log.e(TAG,******设置滑块***********);
        slider.setOnProgressChangeListener(的ChangeListener);
    }



    私人OnProgressChangeListener的ChangeListener =新OnProgressChangeListener(){


        @覆盖
        公共无效onProgressChanged(视图V,INT进度){
            // TODO自动生成方法存根

            setProgress(进度);
            Log.e(TAG,***********进步=+进步);

        }
    };





    @覆盖
    公共无效的OnDraw(帆布油画){
        super.onDraw(画布);


        canvas.drawBitmap(BGR,0,0,NULL);
        canvas.drawCircle(CENTREX,centreY,半径,pTouch);


    } //的OnDraw结束




    保护无效setProgress(INT progress2){
        this.Progress = progress2;
        findCirclePixels();
        无效();

    }


}
 

解决方案

作为替代 runOnUiThread ,您可以使用的AsyncTask ,并使用 publishProgress / onProgressUpdate 机制触摸意见。谷歌有一个 pretty的好帖子关于使用的AsyncTask ,其中包括在任务运行的方式,以及哪些在UI线程中运行。做你的计算中 doInBackground ,并调用 publishProgress 每当有数据的某些量子给到用户界面来呈现。然后呈现在 onProgressUpdate 函数的数据。需要注意的是参数两个功能都是很随意的,正如你愿意,你可以定义它们。

编辑:在重新阅读你的问题,我不知道如果使用一个单独的线程是要走的路,因为你正在从用户的输入,你正在你的计算。这是可能的,有可能是滑动条移动和渲染之间的显著滞后,特别是如果计算线程被饿死。如果计算是足够强烈,值得一个单独的线程,你可能要考虑在计算折腾了一个进度条,而不是由具有渲染滞后太远滑​​杆其背后的运动迷惑用户。要么,你就必须在某些逻辑添加到取消如果检测到更改和当前的渲染运算的线程是不完整的,然后再次用中火它关闭新的参数。有关取消更多信息 AsyncTasks ,读的的文档的AsyncTask

EDIT2:当我实现了我的AsycTask,我定义包含了所有我需要的元素的对象:视图,游标,异常等,并使用了作为来回传递的参数。我暗示相同的概念,TouchViewData,因为线程不能碰的视图。只要包装好了,你需要的数据,并让该线程疯狂就可以了。

 公共类MyAsyncTask扩展的AsyncTask< TouchViewData,对象,空虚> {

    / *
     *这些运行在UI线程上,并且可以访问浏览
     * /
    保护无效onProgressUpdate(对象...值){
      //这里就是神奇的发生!
      //更新您的看法,开放的对话,面包用户,不管做什么!
    }

    在preExecute保护无效(){
      // preP任何你需要的线程
    }

    保护无效onPostExecute(){
      //敲定任何渲染或清理
    }

    保护无效onCancelled(){
      //被取消了!时间来清理
    }

    / *
     *这将运行在独立的线程,并且无法改变查看在所有
     * /
    公共无效doInBackground(TouchViewData ... PARAMS){
      而(stillCalculating&安培;&安培;!isCancelled()){
        //做你的计算,那么...
        publishProgress(...); //传递一些数据到UI线程渲染
      }
      返回;
    }

}
 

在你的活动:

  MyAppTask计算器=新MyAppTask();
calculator.execute(touchViewInstanceData,someObject);

...

//如果您需要:
calculator.cancel();
 

Hi all i've an app that places a circle on a bitmapa and with a slidebar alters the rgb values of the pixels within the circle. i'd like to use asynctask to speed up the process of altering the pixels. i'm not sure where to start. i've commented out some code at the bottom of the activity file as this is my first attept at it:). could anyone point me in the correct direction in how to implement this. The activity invokes a custom view(touchview), as i understand the asynctask must be instantiated on the UI thread. i'm thinking of initializing the slidebar ect in onPreExecute(), but not sure how to put all the worker stuff in doInBackground(). Any help will be appreciated, thanks Matt.

public class Jjilapp extends Activity {


    private Button b1;

    private static final String TAG = "*********jjil";


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "***********inside oncreate about to set contentview = ");
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.touchview);
        final TouchView touchView = (TouchView)findViewById(R.id.touchview); 
        final HorizontalSlider slider = (HorizontalSlider)findViewById(R.id.slider); 

        touchView.initSlider(slider);


        b1 = (Button)findViewById(R.id.button1);
        b1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Log.e(TAG, "onClickButton1");

            }
        });



    }//end of oncreate

   /* private class UpdateCirclePixels extends AsyncTask<Integer,Integer,Integer>{

        @Override
        protected void onPreExecute(){
            final TouchView touchView = (TouchView)findViewById(R.id.touchview); 
            final HorizontalSlider slider = (HorizontalSlider)findViewById(R.id.slider); 

            touchView.initSlider(slider);

        }



        @Override
        protected Integer doInBackground(Integer... arg0) {
            // TODO Auto-generated method stub

            publishProgress(progress);
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progress){


        }


    }//end of AsyncTask     */


}//end of jjilapp

.

public class TouchView extends View{


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




    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);



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


        //pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));



    }// end of touchView constructor


    public void findCirclePixels(){ 



        for (int i=centreX-50; i < centreX+50; ++i) {
            for (int y=centreY-50; y <centreY+50 ; ++y) {

    if( Math.sqrt( Math.pow(i - centreX, 2) + ( Math.pow(y - centreY, 2) ) ) <= radius ){

                    bgr.setPixel(i,y,Color.rgb(Progress+50,Progress,Progress+100));
                }
            }
        }

        }// end of changePixel()




    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

            case MotionEvent.ACTION_DOWN: {

                centreX = (int) ev.getX();
                centreY = (int) ev.getY();
                findCirclePixels();
                invalidate();

                break;
            }

            case MotionEvent.ACTION_MOVE: {

                    centreX = (int) ev.getX();
                    centreY = (int) ev.getY();
                    findCirclePixels();
                    invalidate();
                    break;

            }           

            case MotionEvent.ACTION_UP: 

                break;

        }
        return true;
    }//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);

        }
    };





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


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


    }//end of onDraw




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

    }


}

解决方案

As an alternative to runOnUiThread, you can use an AsyncTask, and use the publishProgress/onProgressUpdate mechanism to touch the Views. Google has a pretty good post about using AsyncTask, including which methods run in the task, and which ones run in the UI thread. Do your computations in doInBackground, and call publishProgress whenever there is some quanta of data to give to the UI to render. Then render that data in the onProgressUpdate function. Note that the parameters for both functions are quite arbitrary, and you can define them as you wish.

edit: Upon re-reading your question, I wonder if using a separate thread is the way to go, since you are taking input from the user as you are making your computations. It's possible that there could be a significant lag between the slider bar movement and the rendering, especially if the computation thread gets starved. If the computations are intense enough to warrant a separate thread, you may want to consider tossing up a progress bar during the computations, rather than confuse a user by having the rendering lag too far behind their movement of the slider bar. Either that, or you'll have to add in some logic to cancel the computation thread if a change is detected and the current render is incomplete, then fire it off again with the new parameters. For more information about cancelling AsyncTasks, read the introduction section(s) of the documentation for AsyncTask.

edit2: When I implemented my AsycTask, I defined an Object that contained all the elements I'd need: Views, Cursors, Exceptions, etc., and used that as a parameter for passing back and forth. I'm implying the same concept with TouchViewData, since the thread can't touch the View. Just pack it up with the data you need, and let the thread go crazy on it.

public class MyAsyncTask extends AsyncTask<TouchViewData, Object, void> {

    /*
     * These run on the UI thread, and can access the Views
     */
    protected void onProgressUpdate(Object... values) {
      // Here's where the magic happens! 
      //   Update your views, open dialogs, Toast the user, whatever!
    }

    protected void onPreExecute() {
      // Prep anything you need for the thread
    }

    protected void onPostExecute() {
      // Finalize any rendering or cleanup
    }

    protected void onCancelled() {
      // Got cancelled! Time to clean up
    }

    /*
     * This runs in a separate thread, and can not change the View at all
     */
    public void doInBackground(TouchViewData... params) {
      while(stillCalculating && ! isCancelled()) {
        // Do your calculations, then...
        publishProgress(...); // pass some data to the UI thread to render
      }
      return;
    }

}

In your Activity:

MyAppTask calculator = new MyAppTask();
calculator.execute(touchViewInstanceData, someObject);

...

// if you need to:
calculator.cancel();

这篇关于实现AsyncTask的提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆