AsyncTask ProgressDialog не обновит диалоговое сообщение

#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 будет удален? Ок. Если я установил сообщение, добавьте его!! Есть ли что-то еще? Я не могу понять это