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 внутренним классом деятельности