数据将从另一个方法返回,而不是一个方法,并行线程将其返回

时间:2012-03-23 17:08:28

标签: android multithreading android-asynctask httpconnection


我有一个扩展AsyncTask的类。
在doInBackground()方法中,我连接到服务器并获取数据。
所述类具有方法get(),该方法将该数据返回给用户。
所以我在这个类中调用execute()方法,不久之后,返回一个成员变量“response”。
但是返回null,因为尚未建立连接。
所以,我在onPostExecute()中设置了变量“response”,并希望从这里返回主线程。
如果不使用这样的循环,我将如何做到这一点:

while(! gotResponse) continue;

我的伪代码:

//Main thread
class blah {
   .... onCreate(..) {
      ConHelper ch = new ConHelper();
      String data = ch.get();
   }
}
class ConHelper extends AsyncTask<...>{
   private String response;
   private boolean gotResponse;

   ... get() {
      this.execute(...);
      while(! this.gotResponse) continue;
      return this.response;
   }
   ... doInBackground(..) {
      // connect and get data.
   }
   ... on postExecute(...) {
      //set response and gotResponse from obtained data.
   }

3 个答案:

答案 0 :(得分:2)

AsyncTask的概念是任务本身启动结果可用后需要完成的任何事情。像get()这样的方法无法实现。当然,在结果可用之前,不要尝试等待主(UI)线程。 (顺便说一句,AsyncTask已经定义了一个get()方法来检索结果。如果结果不可用,它将阻塞直到它们为止。不要从UI线程调用它。)

这样做的方法是让onPostExecute()启动结果可用后需要完成的任何操作。在doInBackground()的所有耗时工作完成后,在UI线程上调用此方法。

编写您的UI逻辑(onCreate()等),以便它不必等待结果,并且当结果尚不可用时它可以工作。 (例如,您可以在显示data的位置显示空白字段或“请稍候”消息。或者您可以弹出“工作”警报对话框并将其从{{1}中删除}}。)

答案 1 :(得分:1)

我不确定是否有办法在Android框架中执行此操作。如果您担心旋转,那么您可以执行以下操作:

final Object lock = new Object();

// wait until the value has been set
synchronized (lock) {
    // we do a while loop to protect against interrupts and race conditions
    while(response == null) {
        try {
            lock.wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return;
        }
    }
}

然后,当您准备好设置响应时,您需要执行以下操作:

synchronized (lock) {
    response = ...;
    lock.notifyAll();
}

答案 2 :(得分:1)

Ted Hopp的答案就是你要找的。我正在添加这个答案来发布一些代码。正如Ted暗示的那样,你的活动应该在AsyncTask完成它的同时开展业务。

完成ConHelper后,它可以通过onPostExecute访问活动,get在主线程上运行

您当然不希望从onCreate致电while,因为get中的ConHelper循环只会导致主线程被阻止,从而击败首先创建Activity的完整原因。

关键是您要构建ConHelper,以便它可以在不访问data中获得的任何数据的情况下运行。如果你不能在onCreate示例中没有变量String的情况下继续,那么从主线程中移除工作对你没有帮助。

所以,让我们假设你想要做一些冗长的电话,它会返回你想要在TextView中显示的public class MyActivity extends Activity { protected TextView myTextView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // or whatever layout you have myTextView = (TextView)findViewById(R.id.mytextview); //or whatever widgets/ids you use ConHelper ch = new ConHelper(); ch.execute(); } class ConHelper extends AsyncTask<..., Void, String>{ protected String doInBackground(..) { // connect and get data. return <some lengthy method call that returns a String>; } protected void onPostExecute(String resultFromDoInBackground) { myTextView.setText(resultFromDoInBackground); } } } 。这是一种方法:

{{1}}