Loaders (and why we should use them)

Post on 23-Jun-2015

202 views 0 download

Tags:

description

In this presentation I'm talking about powerful tool for asynchronous loading which is provided by Android framework - loaders. Why guys from Android team added this tool and how we can customise it? We'll try to find answers for these questions.

Transcript of Loaders (and why we should use them)

почему с ними стоит дружить?

Loaders

Проблемахотим плавный графический интерфейс без

тормозов

Решениевыносим все время-затратные процессы в

фон

Простейший случай

Инструменты для решениявстроенные в Java классы для роботы с

многопоточностью (Thread, Runnable, etc)

Недостатки● никаких “удобств” для организации

межпроцессного взаимодействия ○ много кода - легко запутаться и допустить ошибку

● не адаптированны для Android’а○ проблемы с производительностью (если не

использовать пул потоков)○ ничего не знают про жизненный цикл

компонентов

Частное решение - AsyncTask● Значительно упрощает межпроцессное

взаимодействие● Использует пул (производительность++)

Активности не вечныочень не вечны...

Проблемафоновые процессы должны “переживать” пересоздание активности и доставлять

результат в новую активность

Решениеиспользовать компоненты отвязанные от

контекста активности

Инструменты для решения● сервис (Robospice)● RxJava + фрагменты● лоадеры● веселые комбинации из предыдущих трех

Справедливости ради, нужно отметить, что асинктаски все еще пользуются популярностью

Обычно, случается совсем не сразу после сокрытия активности + сетевые запросы не настолько длинные

Сервисы+маловероятно, что система убъет приложение+много хорошо развитых библиотек-трудности взаимодействия с сервисом-библиотеки Гуглом не поддерживаются, судьба их туманна

RxJava+ бОльшая ориентированность на событийную модель-+другая парадигма программирования-без Retrolambda очень много шаблонного кода

Кто такой этот ваш лоадер?Это кто-то умеющий:● загрузить данные● хранить их в себе● отслеживать изменения в данных и доставлять

новые данные● реагировать на события жизненного цикла

Состояния Loader’а● started - лоадер загружает/хранит данные и следит

за обновлениями● stopped - лоадер следит за обновлениями, но не

сообщает о них● reset - лоадер не содержит в себе данных и не

следит за изменениями

LoaderManager● привязывается к активности/фрагменту и

переживает configuration change

● хранит ссылки на лоадеры

● обеспечивает жизненный цикл лоадеров

Методы LoaderManager‘а○ initLoader() - создает и запускает лоадер. Если

лоадер содержит данные - возвращает их немедленно

○ restartLoader() - создает или пересоздает лоадер,

при этом данные загружаются заново

○ destroyLoader() - уничтожает лоадер

LoaderCallbacksТочка коммуникации View и LoaderManager

public class SampleActivity extends Activity implements LoaderManager.LoaderCallbacks<D> {

public Loader<D> onCreateLoader(int id, Bundle args) { // фабричный метод для лоадера }

public void onLoadFinished(Loader<D> loader, D data) { // обработка результатов }

public void onLoaderReset(Loader<D> loader) { // освобождение ресурсов }}

До API level 11 у активности были такие методы:

● public void startManagingCursor(Cursor)

● public void stopManagingCursor(Cursor)

● public Cursor managedQuery(Uri, String, String, String, String)

Почему все началось с курсоров?они и до сих пор есть, но deprecated

Но что-то было не так...+активность сама обслуживает курсор-курсор пересоздавался при пересоздании активности-все в UI потоке

getLoaderManager().initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { return new CursorLoader(getActivity(), "content://com.foo.bar/dog", null, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { if (cursor != null && cursor.moveToFirst()) someView.setText(cursor.getString(0)); } @Override public void onLoaderReset(Loader<Cursor> cursorLoader) { // если бы тут был курсор адаптер, мы бы свапнули курсор }});

CursorLoader все порешал

Реализация собственного Loader’а● рекомендуется использовать AsyncTaskLoader

● нужно будет переопределить○ loadInBackground()

○ onStartLoading()

○ onStopLoading()

○ onReset()

○ onCanceled()

○ deliverResult(D results)

● loadInBackground()

○ Фоновая операция. Именно в ней данные загружаются.

● onStartLoading()

○ проверить нет ли у нас загруженных данных и если есть,

то вернуть их немедленно

○ если данных нет, то форсировать их загрузку

○ запустить механизм, который будет отслеживать

изменения в данных

● onStopLoading()

○ перестать уведомлять о новых данных, но быть готовым к

старту

● onReset()

○ остановить загрузку

○ прекратить отслеживать изменения данных

● onCanceled()

○ попытаться остановить текущую загрузку

○ почистить загруженные данные

● deliverResult(D results)

○ если лоадер в reset состоянии - освободить ресурсы

○ иначе доставить новые данные и освободить ресурсы

устаревших данных

Сейчас я полезу в идею, показать вам немного кода для кастомного лоадера.

Наверняка что-то повлится, так что заранее прошу прощения за косячки ;)

Loader’ы+безболезненно переживают пересоздание+хорошо документированны+”официальный” инструмент-приложение могут убить-жизненный цикл не самый простой

Мораль● не стоит пренебрегать лоадерами

● для простого сетевого взаимодействия лоадеры

вполне могут подойти

● можно использовать лоадеры как фасад к

другому инструменту асинхронной загрузки

● Серия статей про Loaders (by Alex Lockwood)● Android networking without pain (презентация)● Modern techniques for implementing REST clients

on Android 4.0 and below● CWAC-LoaderEx and Failed Abstractions● Android tutorial to learn through small projects

(оно на китайском)● Пример на GitHub

Интересности найденные в процессе подготовки презенташки

это все ссылочки - можно кликать

Спасибо за внимание!

Мои контакты:Миша Пустовит

Stanfyhttps://google.com/+ПустовитМихаил