2013-10-27 43 views
17

Tôi đang sử dụng AsyncTask lớp với chữ ký sau đây:Làm thế nào để xử lý các giá trị trả về từ 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); 
} 

Tôi cố gắng để gọi nó từ lớp khác thông qua:

ApiAccess apiObj = new ApiAccess (0, "/User"); 
// String signupResponse = apiObj.execute(nameValuePairs); 
String serverResponse = apiObj.execute(nameValuePairs); //ERROR 

Nhưng ở đây tôi có được điều này lỗi:

Type mismatch: cannot convert from AsyncTask<List<NameValuePair>,Integer,String> to String 

Tại sao khi tôi chỉ định String làm thông số thứ ba trong Lớp học dòng mở rộng?

+0

Phương thức thực hiện trả về 'AsyncTask' không phải là kết quả. Nếu bạn muốn trả lại một số kết quả từ asyncTask hoặc cung cấp một số dữ liệu, hãy sử dụng [protocol] (http://stackoverflow.com/a/26820666/2835520) – IgniteCoders

Trả lời

29

Bạn có thể nhận kết quả bằng cách gọi phương thức get() của AsyhncTask trên AsyncTask được trả về, nhưng nó sẽ biến nó từ một tác vụ không đồng bộ thành một tác vụ đồng bộ vì nó chờ kết quả.

String serverResponse = apiObj.execute(nameValuePairs).get(); 

Vì bạn có AsyncTask của bạn trong một lớp học riêng biệt, bạn có thể tạo một lớp giao diện và khai báo nó trong AsyncTask và thực hiện các lớp giao diện mới của bạn như đại biểu trong lớp mà bạn muốn truy cập vào các kết quả từ. Hướng dẫn tốt là ở đây: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?.

Tôi sẽ cố gắng áp dụng liên kết ở trên cho ngữ cảnh của bạn.

(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"); 
     } 
    } 
} 

(lớp chính của bạn, mà thực hiện 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

Trong trường hợp ai đó muốn thực hiện đồng bộ, AsyncTask không nên được sử dụng, đây là một ý tưởng tồi. –

+3

Tôi biết, nhưng tôi đã cố gắng để cho anh ta cái nhìn sâu sắc về lý do tại sao anh ta có lỗi, vì đó là những gì anh ta hỏi về – frogmanx

0

Vui lòng đọc AsyncTask. Bạn có thể nhận kết quả theo phương pháp onPostExecute. Bạn không thể làm điều gì đó như:

String serverResponse = apiObj.execute(nameValuePairs); 

vì không đồng bộ.

+0

nhưng tôi gọi nó từ bên ngoài như thế nào tôi có thể nhận được kết quả ở đó? – Maven

+0

Bạn có thể viết một cuộc gọi lại được gọi bởi asyncTask (phương thức onPostExecute) và được thực hiện ở bên ngoài. – Devrim

0

Vấn đề là khi bạn gọi thực hiện, các Đối tượng AsyncTask được trả về, nhưng không phải là kết quả. Kết quả được tính toán trong nền. Loại kết quả cuối cùng sẽ là một Chuỗi (như bạn đã chỉ định) và sẽ được chuyển đến onPostExecute().

Bạn nên sử dụng AsyncTask như sau:

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); 
    } 
} 

Lưu ý rằng trong ví dụ của bạn, bạn không được trở về kết quả trong doInBackground(), mà bạn nên.

3

Tôi sẽ đề xuất triển khai Trình xử lý cuộc gọi xử lý. Bạn sẽ chuyển bộ xử lý (hoặc hoạt động) của đoạn đó cho AsyncTask, AsyncTask sẽ gọi khi nó được hoàn thành. AsyncTask cũng có thể trả về một đối tượng tùy ý.

Dưới đây là một ví dụ AsyncTask, mà tôi có trong tập tin riêng của mình (không subclassed):

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); 
    } 
} 

dụ này giả định rằng AsyncTask của bạn cần một miếng kẹo và một Popsicle.Sau đó, nó sẽ trả lại một món tráng miệng cho mảnh của bạn.

Bạn có thể xây dựng và chạy AsyncTask trong một dòng từ mảnh của bạn với:

(new MyTask(mFragmentHandler, candyCane, grapePop)).execute(); 

Nhưng tất nhiên, trước tiên bạn sẽ cần phải thiết lập xử lý của đoạn (myFragmentHandler). Để làm điều này, mảnh của bạn (hoặc hoạt động) sẽ giống như thế (chú ý "thực hiện 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; 
    } 

} 

Nếu bạn sử dụng các mẩu mã, một nút bấm sẽ kích hoạt AsyncTask. Đoạn gọi sẽ tiếp tục thực thi trong khi AsyncTask đang xử lý. Sau đó, khi AsyncTask kết thúc, nó sẽ gửi một tin nhắn đến đoạn nói rằng nó đã hoàn thành, và truyền một đối tượng với thông báo. Tại thời điểm này, đoạn sẽ thấy thông báo, và làm bất cứ điều gì bạn muốn.

Lưu ý: Có thể có lỗi chính tả. Điều này được cắt từ một mã rất lớn và phức tạp.

+0

tôi nghĩ rằng chúng ta nên giữ một tham chiếu tuần về xử lý bên trong AsyncTask – Sayem

+0

Có một tham chiếu. Tôi không chắc ý bạn là gì. Tôi nghĩ rằng các định dạng mã là xấu, vì vậy tôi đã cố gắng sửa chữa nó. Có lẽ ban đầu nó không rõ ràng. –

+0

Cảm ơn Bremen_matt vì giải pháp này. Tôi đã có thể khắc phục sự cố đồng bộ hóa giữa hai tác vụ Async bằng cách sử dụng giải pháp này. –

Các vấn đề liên quan