0

Я пытаюсь организовать код приложения, разделяющий классы AsyncTask из Activity или Fragments. Серфинг этого форума я узнал о решении "интерфейс и слушателя":Возврат нескольких данных из AsyncTask

Interface.java

public interface TaskCompleteListener<T> { 
    public void onTaskComplete(T result); 
} 

AsyncTask.java

[...] 
@Override 
protected void onPostExecute(String JSONResponse) { 
    // using Gson library I convert JSONResponse string to POJO objects... 
    listener.onTaskComplete(result); 
} 

Activity.java

public class MainActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

    // start AsyncTask... 
    } 

    // Inner class implementing interface 
    public class LoadTaskCompleteListener implements TaskCompleteListener<Object> { 
     @Override 
     public void onTaskComplete(Object result) { 
      updateUI(result); 
     } 
    } 

    public void updateUI(Object result) { 
    // here you can manage UI updating, using result object 
    } 
} 

UPDATE DataHelper.java

public class DataHelper { 

    private AsyncTaskCompleteListener<Object> listener; 

    public DataHelper(AsyncTaskCompleteListener<Obejct> listener) { 
     this.listener = listener; 
    } 

    // Multiple AsyncTask are defined here... 
} 

Ну, мне нравится эта картина так много, но: что если в деятельности (или его фрагмент) У меня есть несколько запросов , с различным типом результатов (один объект, массив, список) и различные бизнес-логики для их управления? Я не могу справиться с этим, используя один обратный вызов. Есть идеи? Должен ли я добавить несколько обратных вызовов внутри интерфейса? Я действительно застрял в этом. У меня есть один файл с именем DataHelper с несколькими AsyncTask внутри (что-то вроде веб-геттеров). Естественно, я могу отказаться от этого подхода, если вы предложите любую другую альтернативу.

+0

Можете ли вы опубликовать код, в котором вы инициируете 'слушателя'? –

+0

См. Обновление UPDATE.Я передаю его конструктору DataHelper, удобному классу для цели извлечения данных. – Jumpa

ответ

0

Обратите внимание, что определение onTaskComplete() принимает в качестве аргумента универсального типа, тип T:

onTaskComplete(T result); 

это означает, что вы можете передать в любом типе объекта, один объект, массив, список, и т.д.

Относительно того, как обрабатывать разные результаты с помощью одного обратного вызова, вы можете использовать Bundle для ввода результата, связанного с ключом, а затем в updateUI() проверить этот ключ и принять соответствующий действия.

Что-то вроде этого (псевдокод, не уверен, если он будет компилировать):

@Override 
protected void onPostExecute(String JSONResponse) { 
    Bundle bundle = new Bundle(); 
    bundle.putString("key_json_response", result); //put the response in a Bundle 
    listener.onTaskComplete(bundle); 
} 

// ..... 
public void updateUI(Object result) { 
    Bundle bundle = (Bundle)result; 
    if(bundle.containsKey("key_json_response")){ 
    String json = bundle.getString("key_json_response"); 
    // process json 
    } else if(bundle.containsKey("key_another_response")){ 
    // process another response 
    } 
} 
+0

Звучит неплохо ... Я просто старался не перемещать бизнес-логику, как JSON, анализируя активность, предоставляя ей возможность использовать объекты. – Jumpa

+0

Нет ничего, что помешало бы вам сделать это. Вы можете разобрать json в 'onPostExecute()', а затем поместить готовый к использованию объект в 'Bundle' вместо того, чтобы помещать ответ' String' json. Вы можете использовать 'Bundle', чтобы помещать любые примитивные типы данных, а также настраиваемые объекты, если они реализуют' Serializable'. –

+0

Вы правы. Я использовал метод bundle.putSerializable для передачи общего объекта Bundle. Лучше ли использовать интерфейс Parcelable? В целом, вы думаете, что мой подход к организации кода будет работать спокойно? – Jumpa

1

Почему бы не вернуть массив объектов в результате? Тогда, если у вас есть более одного объекта внутри этого массива, вы будете знать порядок, в который вы их помещаете, чтобы вы могли использовать более одного набора результатов за раз.

public interface TaskCompleteListener<T> { 
    public void onTaskComplete(T... results); 
} 
+0

Спасибо за ваш ответ, интересная идея, но я должен дождаться завершения всех запросов, прежде чем я смогу обработать результаты, правильно? – Jumpa

+0

Если вы сразу же вернете их, тогда да, вы должны дождаться, когда все они будут завершены. – LuigiPower

1

Обратите внимание, что «обработчик» может быть использован вместо задачи асинхронном и что каждый обработчик может вернуть свое сообщение в сообщение looper с сообщением msg, обертывающим разные данные. Легко обрабатывать многие типы данных, потому что это просто компонент сообщения. Образец here

См. «Process_entity()», где сообщения, содержащие компонент результата, отправляются по образцу кода.

+0

Обработчик отправляет обратно строку, могу ли я отправить «сложные» объекты тоже? – Jumpa

+0

http://loopj.com/android-async-http/doc/com/loopj/android/http/BinaryHttpResponseHandler.html –

+0

См. Образец двоичных данных. сложные объекты должны были бы быть полезными, чтобы быть включенными, я считаю. –

Смежные вопросы