Droidcon Moscow 2015
Взаимодействие между
потоками в Android
Максим Ефимов
Кто я такой
0
- Android team lead @ Redmadrobot
- Делал «Мой Билайн», «Открытие»,
«Альфастрахование»
- Всего выпустил больше 30 Android приложений
- Заморачиваюсь по архитектуре
- Модель потоков в Android
- Какие сложности таит жизненный цикл
- Чем плохи стандартные решения
- Хорошие решения
О чём будем говорить
1
Модель потоков в Android
2
- Main поток - обрабатывает циклы GUI
- Looper - обеспечивает очередь сообщений внутри потока
- Handler - умеет писать и читать сообщения из очереди Looper’а
- Остальные потоки - по умолчанию не имею цикла, делают
«долгие операции»
Примеры долгих операций
3
- Сетевое взаимодействие
- Обращения к базе данных
- Чтение дискового каша
- Преобразование изображений
Жизненный цикл I - Связь с background
4
onCreate onStart onResume onPause
starLoading endLoading
Main thread
Background thread
onClick
Main thread
looper
Жизненный цикл II - В идеальном мире
5
onResume onPause
starLoading endLoading
Main thread
Background thread
onClick
Main thread
looper
Loop showData
Жизненный цикл III - Повернули экран
6
onResume onDestroy
starLoading endLoading
Main thread - первый Activity Instance
Background thread
onClick
Main thread
looper
showData
onResume Loop showData
Main thread - второй Activity Instance
Жизненный цикл IV - Свернули приложение
7
onResume onDestroy
starLoading endLoading
Main thread - первый Activity Instance
Background thread
onClick
Main thread
looper
showData
onResume Loop showData
Main thread - второй Activity
Жизненный цикл - сложности
8
- Поток может вернуть результат в
уничтоженный объект
- Поток может потерять результат
- Необходимо где-то кешировать результаты
- Нужно, чтобы кеширование было удобным
Решения – Thread
9
Button signInButton = (Button) findViewById(R.id.button_auth);

signInButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(final View v) {

final Activity activity = AuthActivity.this;

showProgress();

new Thread(new Runnable() {

@Override

public void run() {

APIFactory.getApi().signIn();

activity.runOnUiThread(new Runnable() {

@Override

public void run() {

goToMainContent();

}

});

}

}).start();



}

});
- Течет память
- Возврат в
уничтоженный
объект
- Необходимо
руками писать в
основной поток
Решения – AsyncTask
10
private class AuthTask extends AsyncTask<Void, Void, Boolean> {



@Override

protected void onPreExecute() {

showProgress();

}



@Override

protected Boolean doInBackground(final Void... params) {

try {

APIFactory.getApi().signIn();

}catch (Exception e){

return false;

}

return true;

}



@Override

protected void onPostExecute(final Boolean result) {

if(!isCancelled() && result) {

goToMainContent();

}

}

}
Button signInButton = (Button) findViewById(R.id.button_auth);

signInButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(final View v) {

new AuthTask().execute();

}

});
- Течет память
- Возврат в уничтоженный объект
Решения – Loader
11
Кода не будет
Пример из документации: 154 строки
Решения – Callback
12
Button signInButton = (Button) findViewById(R.id.button_auth);

signInButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(final View v) {

new AuthRequest(new Callback<Result>(){



@Override

public void handleMessage(final Result result) {

showData();

}



@Override

public void handleError(final Exception exception) {

showError(exception);

}

}).run();

}

});
- Retrofit
- Volley
- RxJava
На самом деле не решают
поставленных проблем
Проблемы решений
13
- Нет привязки к жизненному циклу
- Утечки памяти
- Потеря данных
- Сложная реализация
Хорошие решения – Robospice
14
- Следит за жизненным циклом
- Заточена под сеть
- Есть свой кэш
- Память не течет
- Имеет 100500 плагинов
Хорошие решения – Chronos
15
- Следит за жизненным циклом
- Подхватывает запущенные задачи
- Минималистичен
Chronos - запуск операции
16
class MyActivity extends ChronosActivity {



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);



Button startButton = (Button) findViewById(R.id.button_start);

startButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(final View v) {

runOperation(new MyOperation());

}

});

}

}
Chronos - операция
17
class MyOperation extends ChronosOperation<BusinessObject> {



@Nullable

@Override

public BusinessObject run() {

final BusinessObject result ;

// here you should write what you do to get the BusinessObject

return result;

}



@NonNull

@Override

public Class<? extends ChronosOperationResult<BusinessObject>> getResultClass(){

return Result.class;

}



public final static class Result extends ChronosOperationResult<BusinessObject> {

}

}
Chronos - обработка результата
18
class MyActivity extends ChronosActivity {



public void onOperationFinished(final MyOperation.Result result) {

if (result.isSuccessful()) {

showData(result.getOutput());

} else {

showDataLoadError(result.getError());

}

}



private void showData(BusinessObject data){

//...

}



private void showDataLoadError(Exception exception){

//...

}

}
Chronos - трекинг запусков
19
class MyActivity extends ChronosActivity {



private Data mData;



@Override

protected void onResume() {

super.onResume();

if (mData == null) {

runOperation(new LoadData(), "load_data");

} else {

showData(mData);

}

}



public void onOperationFinished(final LoadData.Result result) {

if (result.isSuccessful()) {

showData(result.getOutput());

} else {

showDataLoadError(result.getError());

}

}

}
Chronos - что еще?
20
- Отмена операций
- Синхронный запуск
- Bradcast результатов
- Opensource
Спасибо за внимание!
21
Вопросы?
me@redmadrobot.ru

More Related Content

PDF
По колено в Си++ г... коде
PDF
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
PPTX
Selenium: приемы работы
PDF
Бессигнатурное обнаружение PHP-бэкдоров
PPTX
Аскетичная разработка браузера
PDF
Асинхронный JavaScript
PDF
Xamarin: кроссплатформенные грабли, Дмитрий Моисеев, СКБ Контур
По колено в Си++ г... коде
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
Selenium: приемы работы
Бессигнатурное обнаружение PHP-бэкдоров
Аскетичная разработка браузера
Асинхронный JavaScript
Xamarin: кроссплатформенные грабли, Дмитрий Моисеев, СКБ Контур

What's hot (20)

PPTX
Selenium: начало работы
ODP
Python infrastructure from scratch
PDF
Web осень 2013 лекция 2
PDF
QA Fest 2019. Андрей Солнцев. Selenide для профи
PPT
Юрий Гольцев - Сервис PLWWW
PPT
plwww (24.03) MEPHI (PHDays)
PDF
Что нового в Perl 5.14
PPTX
Funny JS #1
PPTX
Web осень 2013 лекция 9
PPT
Collider
PPT
Надежда Серкова -- Автоматическая генерация Perl скриптов для тестирования си...
PPTX
Razrabotka testovykh primerov_ts
PPTX
PHP basic
PPTX
Selenium vs AJAX
PDF
Web осень 2013 лекция 6
PPT
Подробная презентация JavaScript 6 в 1
PDF
Применение behave+webdriver для тестирования Web-проектов
PDF
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
PDF
Очередной скучный доклад про логгирование
Selenium: начало работы
Python infrastructure from scratch
Web осень 2013 лекция 2
QA Fest 2019. Андрей Солнцев. Selenide для профи
Юрий Гольцев - Сервис PLWWW
plwww (24.03) MEPHI (PHDays)
Что нового в Perl 5.14
Funny JS #1
Web осень 2013 лекция 9
Collider
Надежда Серкова -- Автоматическая генерация Perl скриптов для тестирования си...
Razrabotka testovykh primerov_ts
PHP basic
Selenium vs AJAX
Web осень 2013 лекция 6
Подробная презентация JavaScript 6 в 1
Применение behave+webdriver для тестирования Web-проектов
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
Очередной скучный доклад про логгирование
Ad

Similar to Droidcon Moscow 2015. Взаимодействие между потоками в Android. Максим Ефимов - Redmadrobot (20)

PPTX
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
PPT
Эффективное программирование на NodeJS
PPTX
iOS and Android Mobile Test Automation
PDF
Mobile automation uamobile
PDF
TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.
PPTX
MVP, Moxy. Как правильно пользоваться
PDF
DI в C++ тонкости и нюансы
PDF
Михаил Давыдов "Масштабируемые JavaScript-приложения"
PPTX
Ловля сетями. Инструменты отладки сетевых запросов приложений / Дмитрий Рыбак...
PPT
Юнит-тестирование и Google Mock. Влад Лосев, Google
PDF
Как построить DOM
PDF
Java осень 2014 занятие 5
PDF
RxJava+RxAndroid (Lecture 20 – rx java)
PDF
Database (Lecture 14 – database)
PDF
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
PPTX
Как стать продуктивным Android разработчиком
PDF
Deep Dive in Magento DI
PPTX
Moxy. Как правильно пользоваться? / Юрий Шмаков (Arello Mobile)
PDF
Илья Ефимов «IoC/DI на примере Autofac»
PDF
Илья Ефимов «IoC/DI на примере Autofac»
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Эффективное программирование на NodeJS
iOS and Android Mobile Test Automation
Mobile automation uamobile
TК°Conf. 10 проблем автоматизации UI и их решение с помощью JDI. Роман Иовлев.
MVP, Moxy. Как правильно пользоваться
DI в C++ тонкости и нюансы
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Ловля сетями. Инструменты отладки сетевых запросов приложений / Дмитрий Рыбак...
Юнит-тестирование и Google Mock. Влад Лосев, Google
Как построить DOM
Java осень 2014 занятие 5
RxJava+RxAndroid (Lecture 20 – rx java)
Database (Lecture 14 – database)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Как стать продуктивным Android разработчиком
Deep Dive in Magento DI
Moxy. Как правильно пользоваться? / Юрий Шмаков (Arello Mobile)
Илья Ефимов «IoC/DI на примере Autofac»
Илья Ефимов «IoC/DI на примере Autofac»
Ad

More from Mail.ru Group (20)

PDF
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
PDF
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
PDF
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
PDF
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
PDF
Управление инцидентами в Почте Mail.ru, Антон Викторов
PDF
DAST в CI/CD, Ольга Свиридова
PDF
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
PDF
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
PDF
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
PDF
WebAuthn в реальной жизни, Анатолий Остапенко
PDF
AMP для электронной почты, Сергей Пешков
PDF
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
PDF
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
PDF
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
PDF
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
PDF
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
PDF
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
PDF
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
PDF
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
PDF
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
Управление инцидентами в Почте Mail.ru, Антон Викторов
DAST в CI/CD, Ольга Свиридова
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
WebAuthn в реальной жизни, Анатолий Остапенко
AMP для электронной почты, Сергей Пешков
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()

Droidcon Moscow 2015. Взаимодействие между потоками в Android. Максим Ефимов - Redmadrobot

  • 1. Droidcon Moscow 2015 Взаимодействие между потоками в Android Максим Ефимов
  • 2. Кто я такой 0 - Android team lead @ Redmadrobot - Делал «Мой Билайн», «Открытие», «Альфастрахование» - Всего выпустил больше 30 Android приложений - Заморачиваюсь по архитектуре
  • 3. - Модель потоков в Android - Какие сложности таит жизненный цикл - Чем плохи стандартные решения - Хорошие решения О чём будем говорить 1
  • 4. Модель потоков в Android 2 - Main поток - обрабатывает циклы GUI - Looper - обеспечивает очередь сообщений внутри потока - Handler - умеет писать и читать сообщения из очереди Looper’а - Остальные потоки - по умолчанию не имею цикла, делают «долгие операции»
  • 5. Примеры долгих операций 3 - Сетевое взаимодействие - Обращения к базе данных - Чтение дискового каша - Преобразование изображений
  • 6. Жизненный цикл I - Связь с background 4 onCreate onStart onResume onPause starLoading endLoading Main thread Background thread onClick Main thread looper
  • 7. Жизненный цикл II - В идеальном мире 5 onResume onPause starLoading endLoading Main thread Background thread onClick Main thread looper Loop showData
  • 8. Жизненный цикл III - Повернули экран 6 onResume onDestroy starLoading endLoading Main thread - первый Activity Instance Background thread onClick Main thread looper showData onResume Loop showData Main thread - второй Activity Instance
  • 9. Жизненный цикл IV - Свернули приложение 7 onResume onDestroy starLoading endLoading Main thread - первый Activity Instance Background thread onClick Main thread looper showData onResume Loop showData Main thread - второй Activity
  • 10. Жизненный цикл - сложности 8 - Поток может вернуть результат в уничтоженный объект - Поток может потерять результат - Необходимо где-то кешировать результаты - Нужно, чтобы кеширование было удобным
  • 11. Решения – Thread 9 Button signInButton = (Button) findViewById(R.id.button_auth);
 signInButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(final View v) {
 final Activity activity = AuthActivity.this;
 showProgress();
 new Thread(new Runnable() {
 @Override
 public void run() {
 APIFactory.getApi().signIn();
 activity.runOnUiThread(new Runnable() {
 @Override
 public void run() {
 goToMainContent();
 }
 });
 }
 }).start();
 
 }
 }); - Течет память - Возврат в уничтоженный объект - Необходимо руками писать в основной поток
  • 12. Решения – AsyncTask 10 private class AuthTask extends AsyncTask<Void, Void, Boolean> {
 
 @Override
 protected void onPreExecute() {
 showProgress();
 }
 
 @Override
 protected Boolean doInBackground(final Void... params) {
 try {
 APIFactory.getApi().signIn();
 }catch (Exception e){
 return false;
 }
 return true;
 }
 
 @Override
 protected void onPostExecute(final Boolean result) {
 if(!isCancelled() && result) {
 goToMainContent();
 }
 }
 } Button signInButton = (Button) findViewById(R.id.button_auth);
 signInButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(final View v) {
 new AuthTask().execute();
 }
 }); - Течет память - Возврат в уничтоженный объект
  • 13. Решения – Loader 11 Кода не будет Пример из документации: 154 строки
  • 14. Решения – Callback 12 Button signInButton = (Button) findViewById(R.id.button_auth);
 signInButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(final View v) {
 new AuthRequest(new Callback<Result>(){
 
 @Override
 public void handleMessage(final Result result) {
 showData();
 }
 
 @Override
 public void handleError(final Exception exception) {
 showError(exception);
 }
 }).run();
 }
 }); - Retrofit - Volley - RxJava На самом деле не решают поставленных проблем
  • 15. Проблемы решений 13 - Нет привязки к жизненному циклу - Утечки памяти - Потеря данных - Сложная реализация
  • 16. Хорошие решения – Robospice 14 - Следит за жизненным циклом - Заточена под сеть - Есть свой кэш - Память не течет - Имеет 100500 плагинов
  • 17. Хорошие решения – Chronos 15 - Следит за жизненным циклом - Подхватывает запущенные задачи - Минималистичен
  • 18. Chronos - запуск операции 16 class MyActivity extends ChronosActivity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 
 Button startButton = (Button) findViewById(R.id.button_start);
 startButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(final View v) {
 runOperation(new MyOperation());
 }
 });
 }
 }
  • 19. Chronos - операция 17 class MyOperation extends ChronosOperation<BusinessObject> {
 
 @Nullable
 @Override
 public BusinessObject run() {
 final BusinessObject result ;
 // here you should write what you do to get the BusinessObject
 return result;
 }
 
 @NonNull
 @Override
 public Class<? extends ChronosOperationResult<BusinessObject>> getResultClass(){
 return Result.class;
 }
 
 public final static class Result extends ChronosOperationResult<BusinessObject> {
 }
 }
  • 20. Chronos - обработка результата 18 class MyActivity extends ChronosActivity {
 
 public void onOperationFinished(final MyOperation.Result result) {
 if (result.isSuccessful()) {
 showData(result.getOutput());
 } else {
 showDataLoadError(result.getError());
 }
 }
 
 private void showData(BusinessObject data){
 //...
 }
 
 private void showDataLoadError(Exception exception){
 //...
 }
 }
  • 21. Chronos - трекинг запусков 19 class MyActivity extends ChronosActivity {
 
 private Data mData;
 
 @Override
 protected void onResume() {
 super.onResume();
 if (mData == null) {
 runOperation(new LoadData(), "load_data");
 } else {
 showData(mData);
 }
 }
 
 public void onOperationFinished(final LoadData.Result result) {
 if (result.isSuccessful()) {
 showData(result.getOutput());
 } else {
 showDataLoadError(result.getError());
 }
 }
 }
  • 22. Chronos - что еще? 20 - Отмена операций - Синхронный запуск - Bradcast результатов - Opensource