Android runOnUiThread объяснение
Я пытаюсь отобразить диалоговое окно прогресса во время выполнения метода onCreate() одного из моих действий, выполнил работу по заполнению экрана в потоке, а затем закрыл диалоговое окно прогресса.
Вот мой onCreateMethod()
dialog = new ProgressDialog(HeadlineBoard.this);
dialog.setMessage("Populating Headlines.....");
dialog.show();
populateTable();
Метод populateTable содержит мой поток и код для закрытия диалога, но по какой-то причине. Действие появляется пустым в течение примерно 10 секунд (выполняется работа populateTable()), и затем я вижу экран. Я никогда не вижу диалоговое окно, есть идеи?
Вот код populateTable():
//Adds a row to the table for each headline passed in
private void populateTable() {
new Thread() {
@Override
public void run() {
//If there are stories, add them to the table
for (Parcelable currentHeadline : allHeadlines) {
addHeadlineToTable(currentHeadline);
}
try {
// code runs in a thread
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.dismiss();
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
}.start();
}
3 ответа
Если у вас уже есть данные "для (Parcelable currentHeadline: allHeadlines)", то почему вы делаете это в отдельном потоке?
Вы должны опрашивать данные в отдельном потоке, а когда он завершит их сбор, затем вызвать ваш метод populateTables в потоке пользовательского интерфейса:
private void populateTable() {
runOnUiThread(new Runnable(){
public void run() {
//If there are stories, add them to the table
for (Parcelable currentHeadline : allHeadlines) {
addHeadlineToTable(currentHeadline);
}
try {
dialog.dismiss();
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
});
}
Это должно работать для вас
public class MyActivity extends Activity {
protected ProgressDialog mProgressDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
populateTable();
}
private void populateTable() {
mProgressDialog = ProgressDialog.show(this, "Please wait","Long operation starts...", true);
new Thread() {
@Override
public void run() {
doLongOperation();
try {
// code runs in a thread
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.dismiss();
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
}.start();
}
/** fake operation for testing purpose */
protected void doLongOperation() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
}
}
Вместо создания потока и использования runOnUIThread
Это идеальная работа для ASyncTask:
В
onPreExecute
, создать и показать диалог.в
doInBackground
подготовьте данные, но не трогайте пользовательский интерфейс - сохраните все подготовленные данные в поле, затем вызовитеpublishProgress
,В
onProgressUpdate
прочитайте базовое поле и внесите соответствующие изменения / дополнения в пользовательский интерфейс.В
onPostExecute
закрыть диалог.
Если у вас есть другие причины, по которым вам нужен поток, или вы добавляете логику, касающуюся пользовательского интерфейса, в существующий поток, то примените метод, аналогичный тому, который я описал, для запуска в потоке пользовательского интерфейса только в течение коротких периодов, используя runOnUIThread
за каждый шаг пользовательского интерфейса. В этом случае вы будете хранить все данные в локальном final
переменной (или в поле вашего класса), а затем использовать его в runOnUIThread
блок.