Я пишу операцию, которая извлекает XML из Интернета через HTTP, а затем анализирует его в DOM. Затем он извлекает некоторые требуемые данные из DOM.
Как вы можете себе представить, это занимает несколько секунд, поэтому я поместил этот код в свой собственный поток, а затем попытался настроить отображение ProgressDialog, пока пользователь этого ждет.
Проблема заключается в том, что ProgressDialog вообще не отображается. Если я удалю вызов увольнять(), то он отображается после завершения работы и, очевидно, просто сидит там...
Вот мой код:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressDialog = ProgressDialog.show(this, "", "Loading...", true);
Thread downloadThread = new Thread(new DownloadVerseThread());
downloadThread.start();
setContentView(R.layout.main);
TextView verseView = (TextView) findViewById(R.id.displayFighterVerse);
TextView dateView = (TextView) findViewById(R.id.displayDateRange);
TextView referenceView = (TextView) findViewById(R.id.displayReference);
try {
downloadThread.join();
} catch (InterruptedException e) {
Log.e(TAG, "Attempted to set the UI values before we were ready.");
return;
}
Log.d(TAG, "Date: " + date);
Log.d(TAG, "Reference: " + reference);
Log.d(TAG, "Scripture: " + scripture);
progressDialog.dismiss();
dateView.setText(date);
referenceView.setText(reference);
verseView.setText(scripture);
}
private class DownloadVerseThread implements Runnable {
@Override
public void run() {
try {
FighterVerseDownloader downloader = new FighterVerseDownloader();
date = downloader.getDateRange();
reference = downloader.getReference();
scripture = downloader.getScripture();
} catch (FighterVersesException e) {
Log.e("FighterVerses", "Failed to get the Fighter Verse", e);
}
}
}
Конструктор FighterVersesDownloader - это то, где выполняется вся работа с точки зрения HTTP и DOM.
Любые идеи о том, что мне не хватает? Я видел несколько подобных потоков при использовании AsyncTask, но я хотел использовать хорошие старомодные потоки напрямую, и предлагаемые решения не применяются.
Я думаю, проблема может быть связана с тем, как вы выполняете потоковую обработку. Когда вы вызываете downloadThread.join(), вы в основном принимаете этот дорогой код и шлепаете его прямо в середине метода, блокируя поток пользовательского интерфейса в процессе.
Вам нужно использовать метод обратного вызова для обработки изменений пользовательского интерфейса при завершении потока. Ваш код должен выглядеть примерно так:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressDialog = ProgressDialog.show(this, "", "Loading...", true);
Thread downloadThread = new Thread(new DownloadVerseThread());
Handler downloadHandler = new Handler();
Runnable downloadCallback = new Runnable (){
public void run(){
setContentView(R.layout.main);
TextView verseView = (TextView) findViewById(R.id.displayFighterVerse);
TextView dateView = (TextView) findViewById(R.id.displayDateRange);
TextView referenceView = (TextView) findViewById(R.id.displayReference);
Log.d(TAG, "Date: " + date);
Log.d(TAG, "Reference: " + reference);
Log.d(TAG, "Scripture: " + scripture);
progressDialog.dismiss();
dateView.setText(date);
referenceView.setText(reference);
verseView.setText(scripture);
}
};
downloadThread.start();
}
private class DownloadVerseThread implements Runnable {
@Override
public void run() {
try {
FighterVerseDownloader downloader = new FighterVerseDownloader();
date = downloader.getDateRange();
reference = downloader.getReference();
scripture = downloader.getScripture();
downloadHandler.post(downloadCallback);
} catch (FighterVersesException e) {
Log.e("FighterVerses", "Failed to get the Fighter Verse", e);
}
}
}
Это будет поддерживать загрузку в фоновом потоке до тех пор, пока она не будет закончена, а не почти сразу же отменит ее обратно в поток пользовательского интерфейса, как это было ранее.
EDIT: Здесь, где я узнал об этом.
Я бы рекомендовал использовать AsyncTask для таких вещей.