ProgressDialog не отображается, если я получаю результат класса AsyncTask из другого класса

Если я возьму результаты, полученные из класса AsynkTask друг от друга, как это:

Register.java:

public void onClick(View v) {
    LoadFermate backgroundFermate = new LoadFermate(Register.this);
    ArrayList<HashMap<String, String>> fermate;
    try{
        fermate = backgroundFermate.execute().get();
        for (HashMap<String, String> fermata:fermate){
            Toast.makeText(Register.this , fermata.get("Nome"), Toast.LENGTH_SHORT).show();
        }
    }catch (InterruptedException e){
        e.printStackTrace();
    }catch (ExecutionException e){
        e.printStackTrace();
    }
}

ProgressDialog не отображается. Если вместо этого я делаю все эти вещи в onPostExecute метод, это показано. Как это возможно?

Я узнал, как получить ценность от другого класса в этом вопросе.

Здесь я публикую класс, в котором я использую ProgressDialog:

LoadingFermate.java:

package com.PacchettoPrincipale.app;

import [...]

public class LoadFermate extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {

    private Context context;

    public LoadFermate(Context context){
        this.context = context;
    }

    private ProgressDialog pDialog;

    private JSONArray mComments = null;
    private ArrayList<HashMap<String, String>> mCommentList;

    //testing on Emulator:
    private static final String DOWNLOAD_FERMATE_URL = "http://10.0.2.2/PrimaAppAndroid/fermate.php";



    //JSON IDS:
    private static final String TAG_COD = "CodFermata";
    private static final String TAG_POSTS = "posts";
    private static final String TAG_NOME = "Nome";

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(context);   //HERE I START THE PDIALOG, and in the onPostExecute method I dismiss it
        pDialog.setMessage("Download fermate...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(Void... voids) {
        updateJSONData();
        return mCommentList;
    }

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> hashMaps) {
        super.onPostExecute(hashMaps);

        pDialog.dismiss();
    }

    private void updateJSONData() {

        mCommentList = new ArrayList<HashMap<String, String>>();

        JSONParser jParser = new JSONParser();
        JSONObject json = jParser.getJSONFromUrl(DOWNLOAD_FERMATE_URL);

        try {

            mComments = json.getJSONArray(TAG_POSTS);

            for (int i = 0; i < mComments.length(); i++) {
                JSONObject c = mComments.getJSONObject(i);

                int CodFermata = c.getInt(TAG_COD);
                String Nome = c.getString(TAG_NOME);


                HashMap<String, String> map = new HashMap<String, String>();

                map.put(TAG_COD, String.valueOf(CodFermata));
                map.put(TAG_NOME, Nome);

                mCommentList.add(map);

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }  
    }
}

2 ответа

Решение

Это связано с тем, что поток пользовательского интерфейса вашего приложения заблокирован, пока вы ожидаете завершения задачи. Ваша программа заблокирована на этой линии:

ermate = backgroundFermate.execute (). get ();

Документация говорит, что "get (): при необходимости ожидает завершения вычисления, а затем извлекает его результат". (Вы можете прочитать это здесь: http://developer.android.com/reference/android/os/AsyncTask.html)

В Android элементы пользовательского интерфейса (такие как диалоговое окно прогресса) не могут обрабатываться несколькими потоками. (Это означает, что вы не можете вызывать какой-либо их метод, иначе вы получите исключение.) Они могут управляться только тем потоком, в котором они были созданы. Этот поток является основным потоком (или потоком пользовательского интерфейса, другими словами) вашего приложения.

Но нам нужно работать в отдельном потоке, и все же мы хотим обновить пользовательский интерфейс!

Эта проблема может быть решена несколькими способами. Либо с помощью Handlers и Runnables, но иногда это может быть сложно. Концепция AsyncTask состоит в том, чтобы выполнять эту работу вместо вас. OnPreExecute() выполняется в потоке пользовательского интерфейса перед выполнением задачи в отдельном потоке, а onPostExecute() также выполняется в основном потоке.

Извините, если вы это знаете. Возвращаясь к вашей проблеме: поскольку вы блокируете поток пользовательского интерфейса, вызывая get () для AsyncTask, onPreExecute() и onPostExecute() не могут работать в потоке пользовательского интерфейса! Они публикуются в главном потоке, но будут работать только после того, как основной поток завершит свою работу. То есть после get () возвращается. Затем диалоговое окно будет показано и закрыто немедленно, поэтому вы его не видите.

Не ждите результата таким образом. Обработайте результат в onPostExecute(), потому что он был разработан для этой цели.

this is just a test, later I'll need this HashMap in the calling class for making a graph(fermate are the liefs). Can I retrieve it in another way? 

marcin_j ответил о get() часть. призвание get() больше не блокирует поток пользовательского интерфейса, делая его асинхронным.

Да, есть способ. Вы можете использовать интерфейс в качестве обратного вызова к действию.

Проверьте ответ по черному поясу

Как вернуть логическое значение из AsyncTask?

Вместо логического значения его HashMap в вашем случае.

Вы также можете сделать свою Asynctask внутренним классом деятельности

Другие вопросы по тегам