【问题标题】:how do i send data back from onPostExecute in an AsyncTask?如何在 AsyncTask 中从 onPostExecute 发回数据?
【发布时间】:2012-03-15 21:36:42
【问题描述】:

我的问题和这个一样 Instance variable of Activity not being set in onPostExecute of AsyncTask or how to return data from AsyncTask to main UI thread 但我想将数据发送回相同的调用活动。意图的 startActivity 不会总是重新启动活动

【问题讨论】:

    标签: android android-intent


    【解决方案1】:

    启用选项是使用侦听器,您可以在其中创建活动实现的接口,例如:

    public interface AsyncListener {
        public void doStuff( MyObject obj );
    }
    

    这样,如果你是 AsyncTask 的子类,很容易添加这个监听器,然后在 onPostExecute() 中,你可以这样做:

    protected void onPostExecute( MyObject obj ) {
       asyncListener.doStuff(obj);
    }
    

    【讨论】:

    • 这是最好的方法,因为它可以让您的 AsyncTask 与 Activity 代码解耦。
    • 如何在 onPostExecute() 中获取 asyncListener 对象?
    【解决方案2】:

    这取决于您的类结构,但如果您的 AsyncTask 是 Activity 中的一个类,那么您可以引用该 Activity 的方法。 你要做的是在你的 onPostExecute 方法中调用你的 Activity 的一个函数,它将在 AsyncTask 中检索到的一些数据传递给你可以使用它的 Activity..

    代码如下所示

    class YourActivity extends Activity {
       private static final int DIALOG_LOADING = 1;
    
       public void onCreate(Bundle savedState) {
         setContentView(R.layout.yourlayout);
         showDialog(DIALOG_LOADING);     
         new LongRunningTask1().execute(1,2,3);
    
       } 
    
       protected Dialog onCreateDialog(int dialogId) {
         switch(dialogId) {
           case DIALOG_LOADING:
               ProgressDialog pDialog = new ProgressDialog(this);
               pDialog.setTitle("Loading Data");
               pDialog.setMessage("Loading Data, please wait...");
               return pDialog;
            default:
                return super.onCreateDialog(dialogId);
          }      
       }
    
       private void onBackgroundTaskDataObtained(List<String> results) {
          dismissDialog(DIALOG_LOADING);
         //do stuff with the results here..
       }
    
       private class LongRunningTask extends AsyncTask<Long, Integer, List<String>> {
            @Override
            protected void onPreExecute() {
              //do pre execute stuff
            }
    
            @Override
            protected List<String> doInBackground(Long... params) {
                List<String> myData = new ArrayList<String>(); 
                for (int i = 0; i < params.length; i++) {
                    try {
                        Thread.sleep(params[i] * 1000);
                        myData.add("Some Data" + i);
                    } catch(InterruptedException ex) {
                    }                
                }
                return myData;
            }
    
            @Override
            protected void onPostExecute(List<String> result) {
                YourActivity.this.onBackgroundTaskDataObtained(result);
            }    
        }
    
    }
    

    所以典型的流程是这样的,设置当前页面的视图,然后显示一个进度对话框。在那之后立即启动异步任务(或任何时候,这并不重要)。

    异步任务完成后,调用活动的函数并将数据传递给它。 不要在异步任务中使用共享数据,否则可能会出现线程问题。相反,一旦你完成了它,就将它传递给活动。如果您想在工作时逐步更新视图,您可以使用 onProgressUpdate

    【讨论】:

    • 感谢您的回答。我不喜欢将 AsyncTask 用作子类。我认为您应该能够使用事件。我认为答案是使用意图,但我这只会创建我不想要的活动的新实例。
    • 您可以轻松地在自己的类中使用 AsyncTask,但这仅在您使用来自多个不同活动的相同逻辑时才有用。在这种情况下,您可以: 1. 使用公共基础类(不是活动,而是扩展活动),然后您将拥有一个可以从异步任务中调用的通用方法。或者更好的是让它们都实现一个公共接口,该接口具有我所描述的回调。将对活动的引用传递给 AsyncTask 的构造函数,并确保 asyncTask 有一个构造函数,该构造函数接受接口类型的参数。
    • 您的最后一个选择是完全放弃 AsyncTask 并将其放入一个服务中,您需要创建一个新线程来执行后台活动(因为默认情况下服务不会在自己的线程中运行) .一个简单的方法是创建一个 IntentService,它会为你创建一个新线程。
    • mobile.tutsplus.com/tutorials/android/… 我已经建立了自己的一段时间,但最终我将其从意图服务更改为常规服务。服务的主要问题是活动之间的通信有点复杂(有很多选择)。你可能会做的是提供更多关于你想要完成的细节,并在一个新线程中询问异步任务或服务/意图服务是否是更好的选择。
    猜你喜欢
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    相关资源
    最近更新 更多