我有一个扩展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.
}
答案 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}}