Подтвердить что ты не робот

Обновление пользовательского интерфейса из потока

Я хочу обновить свой пользовательский интерфейс из потока, который обновляет Progressbar. К сожалению, при обновлении шага прогресса, выведенного из "runnable", индикатор прогресса исчезает! Смена рабочих баров, доступных в onCreate() с другой стороны, работает!

Любые предложения?

public void onCreate(Bundle savedInstanceState) {
    res = getResources();
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
    handler.postDelayed(runnable, 1);       
}

private Runnable runnable = new Runnable() {
    public void run() {  
        runOnUiThread(new Runnable() { 
            public void run() 
            { 
                //* The Complete ProgressBar does not appear**/                         
                pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); 
            } 
        }); 
    }
}
4b9b3361

Ответ 1

Вы должны сделать это с помощью AsyncTask (интеллектуальная задняя нить) и ProgressDialog

AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты в потоке пользовательского интерфейса без необходимости манипулировать потоками и/или обработчиками.

Асинхронная задача определяется вычислением, которое выполняется на фоновом потоке и результат которого публикуется в потоке пользовательского интерфейса. Асинхронная задача определяется тремя универсальными типами, называемыми Params, Progress и Result, и 4 шагами, называемыми begin, doInBackground, processProgress и end.

4 шага

Когда выполняется асинхронная задача, задача выполняет 4 шага:

onPreExecute(), вызывается в потоке пользовательского интерфейса сразу после выполнения задачи. Этот шаг обычно используется для настройки задачи, например, показывая индикатор выполнения в пользовательском интерфейсе.

doInBackground(Params...), вызывается в фоновом потоке сразу же после того, как onPreExecute() завершает выполнение. Этот шаг используется для выполнения фоновых вычислений, которые могут занять много времени. Параметры асинхронной задачи передаются на этот шаг. Результат вычисления должен быть возвращен этим шагом и будет возвращен на последний шаг. Этот шаг также может использовать publishProgress (Progress...) для публикации одного или нескольких единиц прогресса. Эти значения публикуются в потоке пользовательского интерфейса на этапе onProgressUpdate (Progress...).

onProgressUpdate(Progress...), вызывается в потоке пользовательского интерфейса после вызова publishProgress (Прогресс...). Время выполнения undefined. Этот метод используется для отображения любой формы прогресса в пользовательском интерфейсе, пока фоновое вычисление все еще выполняется. Например, его можно использовать для анимации строки выполнения или отображения журналов в текстовом поле.

onPostExecute(Result), вызывается в потоке пользовательского интерфейса после завершения фонового вычисления. Результат вычисления фона передается на этот шаг в качестве параметра. Правила Threading

Существует несколько правил потоковой передачи, которые должны соблюдаться для правильного функционирования этого класса:

Экземпляр задачи должен быть создан в потоке пользовательского интерфейса. execute (Params...) должен быть вызван в потоке пользовательского интерфейса. Не вызывайте onPreExecute(), onPostExecute (Результат), doInBackground (Params...), onProgressUpdate (Прогресс...) вручную. Задача может быть выполнена только один раз (исключение будет выбрано при попытке выполнить второе выполнение).

Пример кода
Что делает адаптер в этом примере, не важно, более важно понять, что вам нужно использовать AsyncTask для отображения диалога для прогресса.

private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
    ProgressDialog dialog;
    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(viewContacts.this);
        dialog.setMessage(getString(R.string.please_wait_while_loading));
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }
    /* (non-Javadoc)
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected ContactsListCursorAdapter doInBackground(Void... params) {
        cur1 = objItem.getContacts();
        startManagingCursor(cur1);

        adapter1 = new ContactsListCursorAdapter (viewContacts.this,
                R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});

        return adapter1;
    }

    protected void onPostExecute(ContactsListCursorAdapter result) {
        list.setAdapter(result);
        dialog.dismiss();
    }
}

Ответ 2

Самое простое решение, которое я видел, чтобы предоставить короткий выполнение в потоке пользовательского интерфейса осуществляется через метод post() представления. Это необходимо, так как методы пользовательского интерфейса не являются повторными. метод для этого:

package android.view;

public class View;

public boolean post(Runnable action);

Метод post() соответствует SwingUtilities.invokeLater(). К сожалению, я не нашел чего-то простого, что соответствует SwingUtilities.invokeAndWait(), но можно построить позднее на основе первого с монитором и флагом.

Итак, вы сохраняете это, создавая обработчик. Вам просто нужно чтобы найти свое мнение, а затем опубликовать его. Вы можете найти свое мнение через findViewById(), если вы, как правило, работаете с id-ed ресурсами. Результирующий код очень прост:

/* inside your non-UI thread */

view.post(new Runnable() {
        public void run() {
            /* the desired UI update */
        }
    });
}

Примечание. По сравнению с SwingUtilities.invokeLater() метод View.post() возвращает логическое значение, указывая, view имеет связанную очередь событий. Поскольку я использовал invokeLater() соответственно. post() в любом случае только для огня и забыть, Я не проверял значение результата. В основном вы должны call post() только после того, как onAttachedToWindow() был вызван на вид.

С наилучшими пожеланиями

Ответ 3

Используйте AsyncTask класс (вместо Runnable). У него есть метод под названием onProgressUpdate, который может повлиять на пользовательский интерфейс (он вызывается в потоке пользовательского интерфейса).

Ответ 4

Если вы используете Handler (я вижу, что вы делаете и, надеюсь, вы создали свой экземпляр в потоке пользовательского интерфейса), то не используйте runOnUiThread() внутри вашего runnable. runOnUiThread() используется, когда вы делаете что-то из потока, отличного от UI, однако Handler уже выполнит ваш runnable в потоке пользовательского интерфейса.

Попробуйте сделать что-то вроде этого:

private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    res = getResources();
    // pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
    mHandler.postDelayed(runnable, 1);
}

private Runnable runnable = new Runnable() {
    public void run() {
        pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
        pB.invalidate(); // maybe this will even not needed - try to comment out
    }
};

Ответ 5

Вам нужно создать Handler в потоке пользовательского интерфейса, а затем использовать его для публикации или отправки сообщения из другого потока для обновления пользовательского интерфейса

Ответ 6

Если вам не нравится AsyncTask, вы можете использовать шаблон наблюдателя. В этом примере используйте ResponseHandler в качестве внутреннего класса в вашей деятельности, затем введите строковое сообщение, в котором будет задан процент выполнения баров... Вам нужно убедиться, что любые изменения в пользовательском интерфейсе выполняются в ResponseHandler, чтобы избежать замораживания UI, то ваш рабочий поток (EventSource в примере) может выполнять требуемые задачи.

Я бы использовал AsyncTask tho, однако шаблон наблюдателя может быть полезен по причинам настройки, а также его легче понять. Также я не уверен, что этот способ широко принят или будет работать на 100%. Im загружает и плагин android теперь, чтобы проверить его

Ответ 7

Как рекомендовано официальной документацией, вы можете использовать AsyncTask , чтобы обрабатывать рабочие элементы короче 5 мс в продолжительности. Если ваша задача займет больше времени, найдите другие альтернативы.

HandlerThread является альтернативой Thread или AsyncTask. Если вам нужно обновить интерфейс от HandlerThread, опубликуйте сообщение в потоке пользовательского интерфейса Looper и потоке пользовательского интерфейса Handler может обрабатывать обновления пользовательского интерфейса,

Пример кода:

Android: тост в потоке