Правый подход Android: где JSON-ответ должен анализироваться - в потоке пользовательского интерфейса или в другом?

Мне просто интересно - где JSONObject или JSONArray, полученные с веб-сервера, должны анализироваться в приложении Android - в основном пользовательском интерфейсе или должны быть доставлены другому?

Например, я использую библиотеку Volley:

private void fetchResults(){

    RequestQueue queue = Volley.newRequestQueue(mContext);
        String url = AuthenticationRequester.URL_GET_ALL_ORDERS;
        JsonArrayRequest jsonDepartureObj = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray jsonArray) {
                iVolleyCallback.onJSONArraySuccess(jsonArray);
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                // hide the progress dialog
            }
        });
        queue.add(jsonDepartureObj);
}

Так что я должен помещать iVolleyCallback.onJSONArraySuccess(jsonArray); в другое выполнение потока или поддерживать основной поток пользовательского интерфейса?

Предположим, что входящий JSON большой и нужно некоторое время для продолжения?

Тот же вопрос касается AsyncTask и других возможных способов работы с веб-сервисами на Android.

Ответ 1

Предпочтительно, чтобы каждая задача, которая занимает долгое время, должна быть выполнена в другом потоке, чтобы избежать перегрузки MainThread:

AsyncTasks в идеале следует использовать для коротких операций (максимум за несколько секунд). Если вам нужно поддерживать потоки в течение длительных периодов времени, настоятельно рекомендуется использовать различные API, предоставляемые java.util.concurrent пакет Executor, ThreadPoolExecutor и FutureTask.

Итак, если вы знаете, что у вас большие данные, и вам потребуется время, вы будете использовать новый поток, но если данные малы и требуют меньше времени, зачем брать на себя риск? Переместите это в новый поток тоже

Ответ 2

Если, как вы говорите, данные JSON могут быть огромными, и может потребоваться некоторое время для обработки, я думаю, вы могли бы (или должны?) попытаться обработать его в AsyncTask. При этом ваш поток пользовательского интерфейса не будет заморожен во время обработки.

Ответ 3

В большинстве графических интерфейсов (не только Android) существует несколько потоков, имеющих разные роли и обязанности:

  • "Основной поток", выполняющийся с "нормальным" приоритетом диспетчеризации, в основном не имеет ничего общего, кроме как быстро реагировать на требования системы пользовательского интерфейса. Когда "сообщения" поступают для его потребления, этот поток немедленно предупреждает другие потоки, чтобы сообщение могло быть обработано быстро. Как любой хороший менеджер...;-)... они сами не выполняют свою работу. Они передают его другим людям.

  • При использовании асинхронных запросов (JSON... и т.д.) обычно существует небольшой "пул" потоков, которые отвечают за их отправку на хост, получают ответ, выполняют кодирование/декодирование и затем либо действовать на ответ, либо передавать его. Эти потоки тратят почти все свое время на хост. Они работают с чуть более низким приоритетом диспетчеризации.

  • Рабочие потоки, работающие с еще более низким приоритетом, выполняют любую работу, которая занимает много времени. Насколько это возможно, эти потоки не выполняют много ввода-вывода. Они быстро и быстро отбрасывают свои временные фрагменты в любой другой поток, но обычно они потребляют весь свой временной срез, когда могут получить его.

Ответ 4

Потенциально длительные запущенные операции должны всегда выполняться в отдельном потоке или действительно любая работа (в пределах разумного...), которая может быть выполнена на отдельном потоке.

В вашем случае вы используете Volley, поэтому вам очень легко переопределить Request<T> parseNetworkResponse(NetworkResponse response); метод и проанализировать ответ на фоновый поток (поскольку этот метод уже выполняется на фоновом потоке) перед его доставкой. Поскольку это относительно легко для этого, действительно нет причин не анализировать ответ на фоновый поток.

Ответ 5

Попробуйте https://github.com/yakivmospan/volley-request-manager

//Queue using custom listener
RequestManager.queue()
    .useBackgroundQueue()
    .addRequest(new TestJsonRequest(), mRequestCallback)
    .start();

private RequestCallback mRequestCallback = new RequestCallback<JSONObject, ResultType>() {  
@Override
public ResultType doInBackground(JSONObject response) {
    //parse and save response data
    return new ResultType();
}

@Override
public void onPostExecute(ResultType result) {
    //update UI here
    Toast.makeText(getApplicationContext(), "Toast from UI", Toast.LENGTH_SHORT).show();
}

@Override
public void onError(VolleyError error) {
    //handle errors here (UI thread) 
    L.e(error.toString());
}
};