Доступ к ListView из другого потока

382
15 сентября 2017, 19:52

Запускаю метод загрузки данных из БД из потока

Thread thread = new Thread(new Runnable() {
@Override
public void run() {
    getAvailableRecipes();
    }
});
thread.start();

В данном методе происходит присвоение адаптера ListView, но в итоге получаю ошибку, что сделать это можно из UI-потока. Каким образом я могу получить доступ к ListView и другого потока? В C# эта проблема решалась с помощью делегатов, а как обстоят дела в java? Воспроизвести по аналогии вряд ли смогу, поскольку с java на "вы". Есть ли какие-то отработанные методы решения данной проблемы?

Answer 1

Разделите этот метод на два:

  1. загрузка данных (долгая операция)
  2. обновление UI (в вашем случае это присвоение адаптера)

Вторую часть нужно выполнять в UI потоке, можно, например, воспользоваться методом runOnUiThread (русская статья про этот метод):

void getAvailableRecipes() {
    ... загрузка данных ...
    activity.runOnUiThread(new Runnable() {
        ... обновление UI ...
    });
}

Так как такой паттерн:

  • Запустить долгую задачу в фоновом потоке
  • Изменить что-то в UI на основе результатов задачи

часто встречается в андроид-приложениях, то разработчики придумали специальный класс AsyncTask, значительно упрощающий жизнь. Вот русская статья про него. Код с ним выглядит примерно так:

new AsyncTask<Params, Progress, Result> {
     protected Result doInBackground(Params... params) {
          ... долгая фоновая операция ...
     }
     protected void onProgressUpdate(Progress... progress) {
         ... обновление прогресса (можно оставить метод пустым) ...
     }
     protected void onPostExecute(Result result) {
        ... обновление UI ...
     }
 }().execute(param1, param2, ...)

Некоторые пояснения:

  • Params — класс параметров, которые вы будете передавать в execute. Можно не передавать никаких параметров и использовать Void
  • Progress — класс, на основе которого будет обновляться прогресс (например, если AsyncTask скачивает файл, то это может быть Integer, представляющий процент скачанного). Можно никак не отображать прогресс и использовать Void
  • Result — класс, который возвращает метод doInBackground и который принимает метод onPostExecute
READ ALSO
Вылетает чат на firebase

Вылетает чат на firebase

Хочу освоить firebaseПриложение вылетает сразу же после запуска на телефоне

296
Узнать ID устройства по сокету (по IP)

Узнать ID устройства по сокету (по IP)

Есть сервер, запущенный на компьютере:

242
Выбор программ и языка для создания контента

Выбор программ и языка для создания контента

Здравствуйте, У меня появился вопросЯ попыталась найти в гуугле ответ, но нашла какие-то общие мысли и ничего конкретного

259
Mediaplayer растягивает видео по surfaceview

Mediaplayer растягивает видео по surfaceview

Как сделать, чтобы видео было в нормальных пропорциях?

265