publishProgress from inside a function in doInBackground?

前端 未结 5 770
名媛妹妹
名媛妹妹 2020-12-15 17:20

I use an AsyncTask to perform a long process.

I don\'t want to place my long process code directly inside doInBackground. Instead my long process code is located in

5条回答
  •  不思量自难忘°
    2020-12-15 17:46

    If this works please let me know! Note that calling doProgress from anywhere other than a method that has been invoked from doInBackground will almost certainly cause an error.

    Yes, it works. I extended it so that you don't need to pass the AsyncTask as a parameter to your method. This is particularly useful if (like me) you've already written all your methods before deciding that actually you do need to publish some progress, or in my case, update the UI from an AsyncTask:

    public abstract class ModifiedAsyncTask extends AsyncTask{
    
        private static final HashMap> threads 
                 = new HashMap>();
    
        @Override
        protected C doInBackground(A... params) {
            threads.put(Thread.currentThread(), this);
            return null;        
        }
    
        public static  void publishProgressCustom(T... t) throws ClassCastException{
            ModifiedAsyncTask task = null;
            try{
                task = (ModifiedAsyncTask) threads.get(Thread.currentThread());
            }catch(ClassCastException e){
                throw e;
            }
            if(task!=null)
                task.publishProgress(t);
        }
    }
    
    public class testThreadsActivity extends Activity {
    
    /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);        
        }
    
        public void Button1Clicked(View v){
            MyThread mthread = new MyThread();
            mthread.execute((Void[])null);      
        }
    
        private class MyThread extends ModifiedAsyncTask{
    
            @Override
            protected Void doInBackground(Void... params) {
                super.doInBackground(params);
    
                while(true){
                    myMethod(System.currentTimeMillis());               
                    try {
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {                  
                        return null;
                    }
                }           
            }
    
            protected void onProgressUpdate(Long... progress) {
                //Update UI
                ((TextView) findViewById(R.id.textView2)).setText("The Time is:" + progress[0]);
            }
    
    
        }
    
        private void myMethod(long l){
    
            // do something
    
            // request UI update
            ModifiedAsyncTask.publishProgressCustom(new Long[]{l});
        }
    
    }
    

    Feels pretty dirty to me, anyone else have a better way?

    My way is probably worse. I'm calling a static method for doProgress (which I called publishProgressCustom). It can be called from anywhere without producing an error (as if the thread has no corresponding AsyncTask in the hashMap, it won't call publishProgress). The down side is that you have to add the Thread-AsyncTask mapping yourself after the thread has started. (You can't override AsyncTask.execute() sadly as this is final). I've done it here by overriding doInBackground() in the super class, so that anyone extending it just has to put super.doInBackground() as the first line in their own doInBackground().

    I don't know enough about Threads and AsyncTask to know what happens to the HashMap references once the Thread and/or AsyncTask comes to an end. I suspect bad things happen, so I wouldn't suggest anyone try my solution as part of their own unless they know better

提交回复
热议问题