How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?

前端 未结 17 2199
鱼传尺愫
鱼传尺愫 2020-11-21 04:50

I have this two classes. My main Activity and the one that extends the AsyncTask, Now in my main Activity I need to get the result from the OnPostExecute(

相关标签:
17条回答
  • 2020-11-21 05:02

    Hi you can make something like this:

    1. Create class which implements AsyncTask

      // TASK 
      public class SomeClass extends AsyncTask<Void, Void, String>>
      {
      
          private OnTaskExecutionFinished _task_finished_event;
      
          public interface OnTaskExecutionFinished
          {
              public void OnTaskFihishedEvent(String Reslut);
          }
      
          public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
          {
              if(_event != null)
              {
                  this._task_finished_event = _event;
              }
          }
      
          @Override
          protected void onPreExecute()
          {
              super.onPreExecute();
      
          }
      
          @Override
          protected String doInBackground(Void... params)
          {
              // do your background task here ...
      
              return "Done!";
          }
      
          @Override
          protected void onPostExecute(String result)
          {
              super.onPostExecute(result);
              if(this._task_finished_event != null)
              {
                  this._task_finished_event.OnTaskFihishedEvent(result);
              }
              else
              {
                  Log.d("SomeClass", "task_finished even is null");
              }
          }
      }
      
    2. Add in Main Activity

      // MAIN ACTIVITY
      public class MyActivity extends ListActivity
      {
         ...
          SomeClass _some_class = new SomeClass();
          _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
          {
          @Override
          public void OnTaskFihishedEvent(String result)
          {
              Toast.makeText(getApplicationContext(),
                      "Phony thread finished: " + result,
                      Toast.LENGTH_SHORT).show();
          }
      
         });
         _some_class.execute();
         ...
       }
      
    0 讨论(0)
  • 2020-11-21 05:05

    This answer might be late but I would like to mention few things when your Activity dependent on AsyncTask. That would help you in prevent crashes and memory management. As already mentioned in above answers go with interface, we also say them callbacks. They will work as an informer, but never ever send strong reference of Activity or interface always use weak reference in those cases.

    Please refer to below screenshot to findout how that can cause issues.

    As you can see if we started AsyncTask with a strong reference then there is no guarantee that our Activity/Fragment will be alive till we get data, so it would be better to use WeakReference in those cases and that will also help in memory management as we will never hold the strong reference of our Activity then it will be eligible for garbage collection after its distortion.

    Check below code snippet to find out how to use awesome WeakReference -

    MyTaskInformer.java Interface which will work as an informer.

    public interface MyTaskInformer {
    
        void onTaskDone(String output);
    
    }
    

    MySmallAsyncTask.java AsyncTask to do long running task, which will use WeakReference.

    public class MySmallAsyncTask extends AsyncTask<String, Void, String> {
    
        // ***** Hold weak reference *****
        private WeakReference<MyTaskInformer> mCallBack;
    
        public MySmallAsyncTask(MyTaskInformer callback) {
            this.mCallBack = new WeakReference<>(callback);
        }
    
        @Override
        protected String doInBackground(String... params) {
    
            // Here do whatever your task is like reading/writing file
            // or read data from your server or any other heavy task
    
            // Let us suppose here you get response, just return it
            final String output = "Any out, mine is just demo output";
    
            // Return it from here to post execute
            return output;
        }
    
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
    
            // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask
    
            // Make sure your caller is active
    
            final MyTaskInformer callBack = mCallBack.get();
    
            if(callBack != null) {
                callBack.onTaskDone(s);
            }
        }
    }
    

    MainActivity.java This class is used to start my AsyncTask implement interface on this class and override this mandatory method.

    public class MainActivity extends Activity implements MyTaskInformer {
    
        private TextView mMyTextView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mMyTextView = (TextView) findViewById(R.id.tv_text_view);
    
            // Start your AsyncTask and pass reference of MyTaskInformer in constructor
            new MySmallAsyncTask(this).execute();
        }
    
        @Override
        public void onTaskDone(String output) {
    
            // Here you will receive output only if your Activity is alive.
            // no need to add checks like if(!isFinishing())
    
            mMyTextView.setText(output);
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:07

    You can do it in a few lines, just override onPostExecute when you call your AsyncTask. Here is an example for you:

    new AasyncTask()
    {
        @Override public void onPostExecute(String result)
        {
           // do whatever you want with result 
        }
    }.execute(a.targetServer);
    

    I hope it helped you, happy codding :)

    0 讨论(0)
  • 2020-11-21 05:09

    I make it work by using threading and handler/message. Steps as follow: Declare a progress Dialog

    ProgressDialog loadingdialog;
    

    Create a function to close dialog when operation is finished.

       private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            loadingdialog.dismiss();
    
        }
        };
    

    Code your Execution details:

     public void startUpload(String filepath) {
        loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
        final String _path = filepath;
        new Thread() {
            public void run() {
                try {
                    UploadFile(_path, getHostName(), getPortNo());
                    handler.sendEmptyMessage(0);
    
                } catch (Exception e) {
                    Log.e("threadmessage", e.getMessage());
                }
            }
        }.start();
    }
    
    0 讨论(0)
  • 2020-11-21 05:09

    Probably going overboard a bit but i provided call backs for both the execution code and the results. obviously for thread safety you want to be careful what you access in your execution callback.

    The AsyncTask implementation:

    public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,  
    ResultType>
    {
        public interface ExecuteCallback<E, R>
        {
            public R execute(E executeInput);
        }
        public interface PostExecuteCallback<R>
        {
            public void finish(R result);
        }
    
        private PostExecuteCallback<ResultType> _resultCallback = null;
        private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;
    
    
        AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
        {
            _resultCallback = postExecuteCallback;
            _executeCallback = executeCallback;
        }
    
        AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
        {
            _executeCallback = executeCallback;
        }
    
        @Override
        protected ResultType doInBackground(final ExecuteType... params)
        {
            return  _executeCallback.execute(params[0]);
        }
    
        @Override
        protected void onPostExecute(ResultType result)
        {
            if(_resultCallback != null)
                _resultCallback.finish(result);
        }
    }
    

    A callback:

     AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new 
     AsyncDbCall.ExecuteCallback<Device, Device>()
        {
            @Override
            public Device execute(Device device)
            {
                deviceDao.updateDevice(device);
                return device;
            }
        };
    

    And finally execution of the async task:

     new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);
    
    0 讨论(0)
  • 2020-11-21 05:10

    There are a few options:

    • Nest the AsyncTask class within your Activity class. Assuming you don't use the same task in multiple activities, this is the easiest way. All your code stays the same, you just move the existing task class to be a nested class inside your activity's class.

      public class MyActivity extends Activity {
          // existing Activity code
          ...
      
          private class MyAsyncTask extends AsyncTask<String, Void, String> {
              // existing AsyncTask code
              ...
          }
      }
      
    • Create a custom constructor for your AsyncTask that takes a reference to your Activity. You would instantiate the task with something like new MyAsyncTask(this).execute(param1, param2).

      public class MyAsyncTask extends AsyncTask<String, Void, String> {
          private Activity activity;
      
          public MyAsyncTask(Activity activity) {
              this.activity = activity;
          }
      
          // existing AsyncTask code
          ...
      }
      
    0 讨论(0)
提交回复
热议问题