Как обрабатывать возвращаемое значение из AsyncTask

Я использую класс 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 в качестве третьего параметра в строке расширения класса?

Вы можете получить результат, вызвав метод get () AsyhncTask на возвращенной AsyncTask, но он превратит его из асинхронной задачи в синхронную задачу, поскольку он ждет получения результата.

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

Поскольку у вас есть AsyncTask в отдельном классе, вы можете создать класс интерфейса и объявить его в AsyncTask и реализовать свой новый класс интерфейса в качестве делегата в классе, к которому вы хотите получить доступ. Хорошее руководство здесь: Как получить результат OnPostExecute () для основного действия, потому что AsyncTask – это отдельный класс? ,

Я попытаюсь применить вышеуказанную ссылку к вашему контексту.

(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. } 

Я бы предложил реализовать обратный вызов обработчика. Вы передадите обработчик фрагмента (или активности) в 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 и Popsicle. Затем он вернет десерт в ваш фрагмент.

Вы можете построить и запустить AsyncTask в одной строке из вашего фрагмента с помощью:

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

Но, конечно, сначала вам нужно настроить обработчик фрагмента (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; } } 

Если вы используете эти фрагменты кода, нажатие кнопки вызывает функцию AsyncTask. Вызывающий фрагмент будет продолжать выполняться во время обработки AsyncTask. Затем, когда AsyncTask будет завершен, он отправит сообщение фрагменту, в котором говорится, что оно завершено, и передать объект с сообщением. На этом этапе фрагмент увидит сообщение и сделает все, что захочет.

Примечание: могут быть опечатки. Это вырезано из очень большого и сложного кода.

Пожалуйста, прочитайте AsyncTask . Вы можете получить результат по методу onPostExecute . Вы не можете сделать что-то вроде:

 String serverResponse = apiObj.execute(nameValuePairs); 

Потому что он асинхронный.

Проблема в том, что когда вы вызываете 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() , который вам нужно.

Intereting Posts
Как вызвать фрагмент из фрагмента? Служба Android перестает работать, когда телефон заблокирован Как передать ArrayList <CustomeObject> из одного действия в другое? Android: Как автоматически перезапустить приложение после того, как оно было «принудительно закрыто»? Добавление пробелов в макет Android: определить, отключены ли уведомления пользователем Ограничить доступ базы данных Firebase к одному Android-приложению Захват снимка экрана на телефоне Android при просмотре видео и камеры Установить правила proguard в android, можно ли просто шифровать код? Android ListView: как добавить строку с кнопкой Список активов в подкаталоге с помощью AssetManager.list Имеются ли в операционной системе Android такие файлы, как / etc / passwd, / etc / shadow и / etc / group? Как добавить дату в базу данных sqlite Как работает Foreground Service (другой процесс / тот же процесс), когда Android остается низким в памяти Импорт apklib из github с Maven