Java 如何处理 AsyncTask 的返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19624193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle return value from AsyncTask
提问by Maven
I am using AsyncTask
class with the following signature:
我正在使用AsyncTask
具有以下签名的类:
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
private String POST(List<NameValuePair>[] nameValuePairs){
...
return response;
}
}
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
return POST(params);
}
I am trying to call it from other class through:
我试图通过以下方式从其他班级调用它:
ApiAccess apiObj = new ApiAccess (0, "/User");
// String signupResponse = apiObj.execute(nameValuePairs);
String serverResponse = apiObj.execute(nameValuePairs); //ERROR
But here I get this error:
但在这里我得到这个错误:
Type mismatch: cannot convert from AsyncTask<List<NameValuePair>,Integer,String> to String
Why is that when i have specified String
as the third parameter in Class extension line?
为什么当我String
在类扩展行中指定为第三个参数时?
采纳答案by frogmanx
You can get the result by calling AsyhncTask's get() method on the returned AsyncTask, but it will turn it from an asynchronous task into a synchronous task as it waits to get the result.
您可以通过对返回的 AsyncTask 调用 AsyhncTask 的 get() 方法来获取结果,但它会在等待获取结果时将其从异步任务转换为同步任务。
String serverResponse = apiObj.execute(nameValuePairs).get();
Since you have your AsyncTask in a seperate class, you can create an interface class and declare it in the AsyncTask and implement your new interface class as delegate in the class you wish to access the results from. A good guide is here: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?.
由于您在单独的类中拥有 AsyncTask,因此您可以创建一个接口类并在 AsyncTask 中声明它,并在您希望从中访问结果的类中将您的新接口类实现为委托。这里有一个很好的指南:How to get the result of OnPostExecute() to main Activity 因为 AsyncTask 是一个单独的类?.
I will attempt to apply the above link to your context.
我将尝试将上述链接应用于您的上下文。
(IApiAccessResponse)
(IApi访问响应)
public interface IApiAccessResponse {
void postResult(String asyncresult);
}
(ApiAccess)
(API访问)
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
public IApiAccessResponse delegate=null;
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
//do all your background manipulation and return a String response
return response
}
@Override
protected void onPostExecute(String result) {
if(delegate!=null)
{
delegate.postResult(result);
}
else
{
Log.e("ApiAccess", "You have not assigned IApiAccessResponse delegate");
}
}
}
(Your main class, which implements IApiAccessResponse)
(你的主类,它实现了 IApiAccessResponse)
ApiAccess apiObj = new ApiAccess (0, "/User");
//Assign the AsyncTask's delegate to your class's context (this links your asynctask and this class together)
apiObj.delegate = this;
apiObj.execute(nameValuePairs); //ERROR
//this method has to be implement so that the results can be called to this class
void postResult(String asyncresult){
//This method will get call as soon as your AsyncTask is complete. asyncresult will be your result.
}
回答by Devrim
回答by Jeffrey Klardie
The problem is that when you call execute, the AsyncTask object is returned, but not the result yet. The result is computed in the background. The type of the result will eventually be a String (as you specified), and will be passed to onPostExecute()
.
问题在于,当您调用 execute 时,会返回 AsyncTask 对象,但尚未返回结果。结果在后台计算。结果的类型最终将是一个字符串(如您指定的那样),并将传递给onPostExecute()
.
You should use the AsyncTask
as follows:
你应该使用AsyncTask
如下:
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
private String POST(List<NameValuePair>[] nameValuePairs){
...
return response;
}
protected void onPreExecute (){
// this is run on the main (UI) thread, before doInBackground starts
}
protected void onPostExecute (String result){
// this is run on the main (UI) thread, after doInBackground returns
}
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
// run in another, background thread
return POST(params);
}
}
Note that in your example you are not returning the result in doInBackground()
, which you should.
请注意,在您的示例中,您没有在 中返回结果doInBackground()
,而您应该这样做。
回答by bremen_matt
I would suggest implementing a Handler Callback. You would pass the fragment's (or activity's) Handler to the AsyncTask, which the AsyncTask will call when it is finished. The AsyncTask can also pass back an arbitrary object.
我建议实施一个处理程序回调。您可以将片段的(或活动的)处理程序传递给 AsyncTask,AsyncTask 将在完成时调用它。AsyncTask 也可以传回任意对象。
Here is an example AsyncTask, which I have in its own file (not subclassed):
这是一个示例 AsyncTask,我在它自己的文件中(未子类化):
public class MyTask extends AsyncTask<Void, String, String> {
private static final String TAG = "MyTask";
private Handler mCallersHandler;
private Candy mObject1;
private Popsicle mObject2;
// Return codes
public static final int MSG_FINISHED = 1001;
public SaveVideoTask(Handler handler, Candy candyCane, Popsicle grapePop ) {
this.mCallersHandler = handler;
this.mObject1 = candyCane;
this.mObject2 = grapePop;
}
@Override
protected String doInBackground(Void... params) {
// Do all of the processing that you want to do...
// You already have the private fields because of the constructor
// so you can use mObject1 and mObject2
Dessert objectToReturn = mObject1 + mObject2;
// Tell the handler (usually from the calling thread) that we are finished,
// returning an object with the message
mCallersHandler.sendMessage( Message.obtain( mCallersHandler, MSG_FINISHED, objectToReturn ) );
return (null);
}
}
This example assumes that your AsyncTask needs a piece of Candy and a Popsicle. Then it will return a Dessert to your fragment.
此示例假设您的 AsyncTask 需要一块糖果和一根冰棒。然后它将向您的片段返回一个甜点。
You can construct and run the AsyncTask in one line from your fragment with:
您可以使用以下命令在片段中的一行中构建和运行 AsyncTask:
( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute();
But of course, you will first need to set up the fragment's handler (myFragmentHandler). To do this, your fragment (or activity) should look like (NOTE the "implements Handler.Callback"):
但当然,您首先需要设置片段的处理程序 (myFragmentHandler)。为此,您的片段(或活动)应如下所示(注意“实现 Handler.Callback”):
public class MyFragment extends Fragment implements Handler.Callback {
private Handler mFragmentHandler;
private Candy candyCane;
private Popsicle grapePop;
@Override
public void onCreate(Bundle savedInstanceState) {
// Standard creation code
super.onCreate(savedInstanceState);
setRetainInstance(true);
// Create a handler for this fragment
mFragmentHandler = new Handler(this);
// Other stuff...
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
// Inflate the layout
View v = inflater.inflate(R.layout.my_fragment_layout, parent, false );
// The candyCane and grapePop don't need to be set up here, but
// they MUST be set up before the button is pressed.
// Here would be a good place to at least initialize them...
// Perhaps you have a button in "my_fragment_layout" that triggers the AsyncTask...
Button mButton = (Button) v.findViewById(R.id.mButton);
mButton.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute();
}
});
return v;
}
@SuppressWarnings("unchecked")
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MyTask.MSG_FINISHED:
// Let's see what we are having for dessert
Dessert myDessert = (Dessert) msg.obj;
break;
}
return false;
}
}
If you use these pieces of code, a button press will trigger the AsyncTask. The calling fragment will continue to execute while the AsyncTask is processing. Then, when the AsyncTask is finished, it will send a message to the fragment saying that it is finished, and pass an object with the message. At this point, the fragment will see the message, and do whatever you want.
如果您使用这些代码段,按下按钮将触发 AsyncTask。当 AsyncTask 正在处理时,调用片段将继续执行。然后,当 AsyncTask 完成时,它会向片段发送一条消息,说它已完成,并传递一个带有该消息的对象。此时,片段将看到消息,并为所欲为。
Note: There might be typos. This is cut from a very large and complicated code.
注:可能有错别字。这是从一个非常庞大和复杂的代码中剪下来的。