我正在使用具有以下签名的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);
}
我试图通过以下方式从其他类中调用它:
ApiAccess apiObj = new ApiAccess (0, "/User");
// String signupResponse = apiObj.execute(nameValuePairs);
String serverResponse = apiObj.execute(nameValuePairs); //ERROR
但是我在这里得到了这个错误:
Type mismatch: cannot convert from AsyncTask<List<NameValuePair>,Integer,String> to String
为什么我在类扩展行中指定String
作为第三个参数?
答案 0 :(得分:32)
您可以通过在返回的AsyncTask上调用AsyhncTask的get()方法来获得结果,但是当它等待获得结果时,它会将它从异步任务转换为同步任务。
String serverResponse = apiObj.execute(nameValuePairs).get();
由于您将AsyncTask放在一个单独的类中,您可以创建一个接口类并在AsyncTask中声明它,并在您希望从中访问结果的类中将您的新接口类实现为委托。这里有一个很好的指南:How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?。
我将尝试将上述链接应用于您的上下文。
(IApiAccessResponse)
public interface IApiAccessResponse {
void postResult(String asyncresult);
}
(ApiAccess)
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");
}
}
}
(您的主要类,实现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.
}
答案 1 :(得分:3)
我建议实现一个Handler Callback。您可以将片段的(或活动的)处理程序传递给AsyncTask,AsyncTask在完成时将调用它。 AsyncTask也可以传回一个任意对象。
这是一个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);
}
}
此示例假设您的AsyncTask需要一块Candy和一个冰棒。然后它会将一个甜点返回到你的片段。
您可以使用以下代码在片段的一行中构建和运行AsyncTask:
( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute();
但是,当然,您首先需要设置片段的处理程序(myFragmentHandler)。为此,您的片段(或活动)应该看起来像(注意&#34;实现Handler.Callback&#34;):
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;
}
}
如果您使用这些代码,按下按钮将触发AsyncTask。在AsyncTask处理时,调用片段将继续执行。然后,当AsyncTask完成时,它将向片段发送一条消息,告知它已完成,并传递带有该消息的对象。此时,片段将看到该消息,并执行您想要的任何操作。
注意:可能存在拼写错误。这是从非常大而复杂的代码中删除的。
答案 2 :(得分:0)
问题是当你调用execute时,会返回AsyncTask对象,但还没有返回结果。结果在后台计算。结果的类型最终将是一个String(如您所指定的),并将传递给onPostExecute()
。
您应该使用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);
}
}
请注意,在您的示例中,您不会在doInBackground()
中返回结果,您应该这样做。
答案 3 :(得分:-1)
请阅读AsyncTask。您可以使用onPostExecute
方法获得结果。你做不了类似的事情:
String serverResponse = apiObj.execute(nameValuePairs);
因为它是异步的。