#android #multithreading #user-interface
#Android #многопоточность #пользовательский интерфейс
Вопрос:
У меня проблема с long ProgressDialog
в моем приложении. Я хочу установить довольно большую базу данных при первом запуске приложения (преобразованную в текстовый документ, объем базы данных будет чуть меньше 200 страниц). Очевидно, это займет некоторое время, поэтому я хочу отобразить ProgressDialog
пользователю, пока это происходит.
Я пытаюсь выполнить это с помощью an AsyncTask
; Ранее я пытался с помощью a Thread
, но я увяз в проблемах, связанных с сохранением / восстановлением состояния.
Индикатор выполнения обновляется просто отлично. Однако я устанавливаю базу данных в три этапа, и я хотел бы показать эти этапы отдельно, чтобы пользователь имел некоторое представление о том, что происходит, и чтобы каждый процентный пункт на панели не занимал так много времени. И по какой-то причине, хотя я могу установить ход выполнения в диалоговом окне, установка сообщения (или заголовка), похоже, ничего не делает.
Вот код для моего подкласса AsyncTask:
public class InstallDbTask extends AsyncTask<Void, Integer, Void>
{
private static final String TAG = "InstallDbTask";
private static final int READ_RULES = 0;
private static final int WRITE_RULES = 1;
private static final int RW_GLOSSARY = 2;
private ProgressDialog dialog;
private Context context;
public InstallDbTask(Context context) { this.context = context; }
protected void onPreExecute()
{
dialog = new ProgressDialog(context);
dialog.setProgressStyle(STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.show();
}
protected Void doInBackground(Void... params)
{
... Initialization ...
// Number of actions to perform for progress bar
int totalCount = rules.length;
// Literal increment for each action
int incrementCount = 0;
// Integral percentage: incrementCount / totalCount * 100
int total = 0;
// Read rules from XML
for(int i = 0; i < rules.length; i )
{
... Parse XML ...
incrementCount ;
total = (int)(((float)incrementCount / totalCount) * 100);
publishProgress(total, READ_RULES);
}
incrementCount = 0;
// Write rules to DB
SQLiteDatabase database = new DbOpenHelper(context).getWritableDatabase();
for(Rule r : rulesList)
{
... Insert ...
incrementCount ;
total = (int)(((float)incrementCount / totalCount) * 100);
publishProgress(total, WRITE_RULES);
}
totalCount = glossaryTerms.length;
incrementCount = 0;
// Write glossary to DB
String term = null;
for(int i = 0; i < glossaryTerms.length; i )
{
... Insert ...
incrementCount ;
total = (int)(((float)incrementCount / totalCount) * 100);
publishProgress(total, RW_GLOSSARY);
}
database.close();
return null;
}
protected void onProgressUpdate(Integer... progress)
{
dialog.setProgress(progress[0]);
switch (progress[1])
{
case READ_RULES:
dialog.setMessage(context.getString(R.string.load_db1));
break;
case WRITE_RULES:
dialog.setMessage(context.getString(R.string.load_db2));
break;
case RW_GLOSSARY:
dialog.setMessage(context.getString(R.string.load_db3));
break;
}
}
protected void onPostExecute(Void result)
{
dialog.dismiss();
}
}
Обращения в onProgressUpdate
методе выполняются правильно ProgressDialog
, так сказать, просто не получает сообщение. Я что-то делаю не так?
Комментарии:
1. проверьте, какое значение произошло в onProgressUpdate (целое число … прогресс).. System.out.println(«прогресс: » прогресс [0]);
2. Значение progress[0] в порядке; оно используется для обновления индикатора выполнения, который работает. Значение для прогресса [1] тоже в порядке вещей; каждый случай в коммутаторе достигается по мере необходимости. Это просто dialog.setMessage, который, по-видимому, терпит неудачу.
Ответ №1:
Вы должны установить начальное сообщение, прежде чем показывать диалоговое окно. В противном случае вызов dialog.setMessage()
onProgressUpdate()
не имеет никакого эффекта.
Чтобы исправить ваш код, вы должны добавить dialog.setMessage("Some initial message")
(строка сообщения может быть ""
, но она не может быть нулевой) перед вызовом dialog.show()
:
protected void onPreExecute()
{
dialog = new ProgressDialog(context);
dialog.setProgressStyle(STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.setMessage("Installing database, please wait");
dialog.show();
}
Комментарии:
1. Спасибо, это сработало! Есть ли объяснение, почему это так?
2. Я посмотрел его в источниках Android. Если сообщение равно нулю при создании макета диалогового окна (создание происходит при первом вызове show()), текстовое представление, предназначенное для сообщения, удаляется из макета и никогда не добавляется обратно.
3. Я не понимаю, почему существует такой подход. Почему бы не дать возможность установить сообщение во второй момент. TextView будет удален? Ок. Если я установил сообщение, добавьте его!! Есть ли что-то еще? Я не могу понять это