Callback android studio kotlin

Котлин корутины. Часть 4. Переход callback API на корутины

В третьей части этой серии вы узнали, как тестировать корутины через поведение. В этой части мы конвертируем существующий API, который работает на основе методов обратного вызова (колбеков). Заменим колбеки на корутины .

Чтобы на практике увидеть работу с Kotlin Coroutines, Room и архитектурными компонентами, записывайтесь на продвинутый курс по разработке приложения «Чат-мессенжер»

Откройте проект в Android Studio

Для начала откройте проект kotlin-coroutines-repository в Android Studio. Исходный код можно найти в первом уроке.

Это приложение использует компоненты архитектуры и расширяет предыдущий проект для реализации уровня данных, который использует как сетевую, так и локальную базу данных. При щелчке по основному виду он выбирает новый заголовок из сети, сохраняет его в базе данных и отображает его на экране. Найдите минутку, чтобы ознакомиться с новыми классами.

  1. MainDatabase реализует базу данных с использованием Room, которая сохраняет и загружает Title .
  2. MainNetwork реализует сетевой API, который выбирает новый заголовок. Он использует поддельную сетевую библиотеку, определенную в FakeNetworkLibrary.kt для того, чтобы получать названия. Сетевая библиотека будет случайным образом возвращать ошибки.
  3. TitleRepository реализует единый API для извлечения или обновления заголовка путем объединения данных из сети и базы данных.
  4. MainViewModelTest определяет тест для MainViewModel .
  5. FakeNetworkCallAwaitTest это тест, который мы закончим позже в этом уроке.

Исследуйте существующий callback API

Откройте MainNetwork.kt и посмотрите на декларацию fetchNewWelcome()

Откройте TitleRepository.kt чтобы увидеть, как fetchNewWelcome используется для выполнения сетевого вызова с использованием колбеков.

Эта функция возвращает FakeNetworkCall, что позволяет регистрировать слушателя для этого сетевого запроса. Вызов fetchNewWelcome запустит длительный сетевой запрос в другом потоке и вернет объект, который устанавливает addOnResultListener . Ваш код передает обратный вызов addOnResultListener который будет вызван, когда запрос завершится успехом или ошибкой.

Источник

Adapter callback in Android using lambda function of Kotlin

Adapter callback in Android using lambda function of Kotlin:

Kotlin provides a lots of different options for concise code writing. Lambda function or lambdas are similar to Java lambdas. In this post, I will show you one common use case of lambda function.

Adapter and interface :

We need one adapter class for a recycler view. It uses one ViewHolder to load data to the recycler view cells. Adapter is a different class and we need to use it in the Activity we are using for the recycler view.

User interaction part is written inside the ViewHolder of the Adapter. For example, if the user clicks on a button, onClickListener is written inside the ViewHolder.

In Java, to pass the data from the ViewHolder to the activity on any user action, one interface is used. If I write the same pattern in Kotlin :

  1. Create one interface:
  1. Pass that interface to the Adapter and use it in onClick of the button or any other view:
  1. Implement this Interface in the activity and override the onClick method :

The MyAdapter object is created in the activity MyActivity. On item click, it will call the onClick method in this activity.

Adapter and lambda:

The above process is a three step way. We can remove the part of creating a interface class by using lambdas :

  1. Pass one lambda function to the adapter instead of an interface and call that lambda to send back the id:
  1. In the activity, inject the lambda:

That’s all, plain and simple.

Using lambda, it becomes easier to handle user interaction. But interface is more easier for different types of click handlings. For example, if you have more than one type of click handling, then using an interface will make the process smooth. You can define all at one place instead of having different lambdas to pass to the constructor.

Источник

WorkManager — Kotlin APIs

WorkManager provides a set of APIs that makes it easy to schedule asynchronous tasks for immediate or deferred execution that are expected to run even if the app is closed or the device restarts. For Kotlin users, WorkManager provides first-class support for coroutines. In this post I’ll show you the basics of WorkManager with coroutines by building on the WorkManager codelab. So let’s get started!

Читайте также:  Фотострана полная версия для андроид

The basics of WorkManager

The WorkManager library is the recommended choice for any task that should continue to run, even if the user navigates away from the particular screen, the user puts the application in background or the device restarts. Common tasks could be:

  • Uploading logs or reporting data
  • Applying filters to images and saving the image
  • Periodically syncing local data with the network

If your immediate task can end when the user leaves a certain scope such as a screen, we recommend you use Kotlin Coroutines directly.

The WorkManager codelab blurs images and saves the result on disk. Let’s see what was needed to achieve this.

We added the work-runtime-ktx dependency.

We started by implementing our own Worker class. This is where we put the code for the actual work you want to perform in the background. You’ll extend the Worker class and override the doWork() method. As this is the most important class we’ll go over it in detail later. Here’s what the initial implementation looks like.

Then, we build our work request, in our case, we want to perform the work only once so we use a OneTimeWorkRequest.Builder . As input, we set the Uri of the image we want to blur.

Kotlin tip: to create the input data, we can use the workDataOf function that creates the data builder, puts the key-value pair and creates the data for us.

To schedule the work and make it run, we use the WorkManager class. We can provide tasks to be done and constraints to these tasks.

Make the Worker do the work

When you use a Worker , WorkManager automatically calls Worker.doWork() on a background thread. The Result returned from doWork() informs the WorkManager service whether the work succeeded and, in the case of failure, whether or not the work should be retried.

Worker.doWork() is a synchronous call — you are expected to do the entirety of your background work in a blocking fashion and finish it by the time the method exits. If you call an asynchronous API in doWork() and return a Result, your callback may not operate properly.

But what if we want to do asynchronous work?

Let’s complicate our example and say that we want to save the Uris of all the files that have been blurred in the database.

For this I created:

  • A simple BlurredImage entity
  • A dao class to insert and get images
  • The database

Check out the implementation here.

If you have to do asynchronous work, like saving data in the database or doing network requests, in Kotlin, we recommend using a CoroutineWorker .

A CoroutineWorker allows us to do asynchronous work, using Kotlin coroutines.

The doWork() method is a suspend method. So this means that we can easily call our suspending dao here.

By default doWork() uses Dispatchers.Default . You can override this with the Dispatcher that you need. In our case, we don’t need to do this because Room already moves the insert work on a different Dispatcher. Check out the Room Kotlin APIs post for more details.

Start using CoroutineWorker to perform asynchronous work that needs to complete even if the user closes your app.

If you want to learn more about WorkManager, stay tuned for a future series dedicated to covering it in depth. Until then, check out our codelabs and documentation:

Источник

Полный список

— посылаем отложенные сообщения
— удаляем сообщения из очереди
— используем Handler.Callback для обработки сообщений

В прошлых уроках мы отправляли сообщения в очередь, а система сразу же доставала их и перенаправляла в Handler на обработку. Но мы можем настроить сообщение так, чтобы система отправило его на обработку не сразу, а с задержкой. Для этого используются методы sendEmptyMessageDelayed (если используете только what) и sendMessageDelayed (полное сообщение). В них мы можем указать паузу в миллисекундах. Система выждет эту паузу и только потом отправит сообщение в Handler.

Если вдруг поместили такое отложенное сообщение в очередь, а потом решили, что оно не должно уйти на обработку, то его можно из очереди удалить. Для этого используется метод removeMessages.

В прошлых уроках мы создавали свой Handler, и в его методе handleMessage кодили свой алгоритм обработки сообщений. Кроме этого способа Handler также может использовать для обработки сообщений объект, реализующий интерфейс Handler.Callback. У интерфейса всего один метод handleMessage – в нем и прописываем всю логику обработки сообщений. Я пока не встречал практической пользы от этой штуки, но все же разберемся, как ее можно использовать. Может когда и пригодится.

Читайте также:  Первая версия андроида год

Project name: P0831_HandlerMessageManage
Build Target: Android 2.3.3
Application name: HandlerMessageManage
Package name: ru.startandroid.develop.p0831handlermessagemanage
Create Activity: MainActivity

strings.xml и main.xml не трогаем, они нам не нужны. Будем работать с логами.

Мы создаем объект hc типа Handler.Callback. У него есть метод handleMessage, в котором мы будем обрабатывать сообщения. В нашем случае просто читаем атрибут what и выводим значение в лог.

В onCreate создаем handler, используя конструктор Handler (Handler.Callback callback). На вход передаем созданный ранее hc. И теперь Handler будет обрабатывать сообщения не сам, а перепоручит это объекту hc. Далее мы выполняем метод sendMessages , который кладет три сообщения в очередь сообщений. Для этого используется метод sendEmptyMessageDelayed. Это аналог знакомого нам метода sendEmptyMessage с прошлого урока. Он тоже заполняет в сообщении только атрибут what, но при этом он позволяет указать задержку в обработке сообщения. Т.е. сообщение будет извлечено из очереди и отправлено на обработку через указанное количество миллисекунд.

Итак, мы помещаем три сообщения:

1) what = 1, обработка через 1000 мс.
2) what = 2, обработка через 2000 мс.
3) what = 3, обработка через 3000 мс.

Замечу, что отсчет задержки начинается после помещения в очередь, а не после обработки предыдущего сообщения. Т.е. эти сообщения по отношению друг к другу сработают с интервалом в одну секунду.

Все сохраним и запустим приложение. В логе одна за другой будут появляться записи:

10:21:07.759: D/myLogs(332): send messages
10:21:08.786: D/myLogs(332): what = 1
10:21:09.765: D/myLogs(332): what = 2
10:21:10.776: D/myLogs(332): what = 3

Обратите внимание на время этих записей. Первое срабатывает через 1000 мс после помещения в очередь (send messages), второе — через две секунды, третье – через три.

Теперь попробуем удалить сообщение из очереди. Перепишем метод sendMessages:

Используем метод removeMessages, в котором указываем значение атрибута what. Этот метод находит в очереди сообщение с атрибутом what, равным 2, и удаляет его из очереди.

Все сохраняем, запускаем приложение. Смотрим лог:

10:24:49.916: D/myLogs(434): send messages
10:24:50.927: D/myLogs(434): what = 1
10:24:52.948: D/myLogs(434): what = 3

Как видим, сообщение с what = 2 не сработало.

А если будет несколько сообщений с одинаковым значением what? Система удалит первое попавшееся или все?

Проверим. Перепишем sendMessages:

Будем помещать в очередь кучу сообщений. Из них несколько с what = 2. Проверим, какие удалит система.

Запускаем приложение и смотрим лог:

10:29:23.297: D/myLogs(467): send messages
10:29:24.372: D/myLogs(467): what = 1
10:29:26.307: D/myLogs(467): what = 3
10:29:28.364: D/myLogs(467): what = 5
10:29:30.332: D/myLogs(467): what = 7

Все сообщения с what = 2 были удалены. Не забывайте это. А то захотите удалить одно последнее сообщение, а система найдет все подходящие, ожидающие обработки, и снесет их.

У метода removeMessages есть еще реализация с использованием obj. Тут все так же, только система ищет для удаления из очереди сообщения с указанными атрибутами what и obj.

Если хотите запланировать полноценное сообщение, а не просто what, то используйте метод sendMessageDelayed – на вход даете сообщение и указываете задержку обработки.

Есть еще методы sendEmptyMessageAtTime и sendMessageAtTime. Они тоже позволяют указать задержку обработки. Но эта задержка будет отсчитана от времени последнего старта системы, а не от времени помещения в очередь. Если сообщение окажется просроченным на момент помещения в очередь, оно выполняется сразу.

На следующем уроке:

— работаем с Handler и Runnable

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Android programmers blog

Simply about difficult

Поиск по этому блогу

понедельник, 5 октября 2015 г.

Callback’и в Android

Еще решил написать одну заметку по поводу коллбеков. Штука интересная и полезная, без нее редко когда получается что то разумное написать. По этому решил что надо будет написать пару примеров по работе с колбеками.

Для начала хочу сказать что есть разные библиотеки типа EventBus и OttoBus которые сделают всю работу за вас и еще больше сделают… Но иногда эти библиотеки сильно много делают для обычной тривиальной задачи, например вернуть респонс из AsyncTask’a или еще что-то похожее, из-за этого использовать эти библиотеки не целесообразно и достаточно написать один интерфейс и вызывать его в нужном месте по тому или иному событию. Собственно это я сегодня и хочу продемонстрировать на примере приложения.

У нас будет небольшой апп который будет тянуть список спорт. каналов через AsyncTask, парсить то что вернет сервер с помощью кастомного JsonArray и JsonObject и отдавать это все колбеком в активити для отображения в списке.

Читайте также:  Naruto kunoichi trainer full android

Для начала давайте сделаем небольшую настройку. Для работы с интернетом нам нужен премишен в манифесте, давайте его добавим.

И сделаем разметку с списком, все будет елементарно и просто.

Все, с настройками мы закончили, теперь давайте кодить!

Первый вариант Callback’a, получение данных в Activity

Первый вариант у нас будет такой как я описал выше, он имеет вот такую архитектуру:

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

Очень сумбурно, нам нужно более детальное рассмотрение этого способа по этому начну.

У вас должен уже быть создан пустой проект с MainActivity, нам она пока не понадобится, мы ее будем использовать в в самом конце.

Сейчас создайте новый класс который будет называться BackgroundTask, в этом методе у нас будет AsyncTask который у нас будет хватать json строку с удаленного сервера.

Вообще использовать AsyncTask не советую, для таких нужд есть прекрасная библотека Retrofit или Volley или еще куча разных великолепных библиотек которые делают запросы и не валятся при повороте экрана. По этому это чисто пример, так как я сделал запрос лучше не делать, повторюсь, лучше используйте готовые решения.

Вот как то так у нас будет работать наш AsyncTask, но пока что вам не хватает нескольких классов которые выполняют кое какую работу, давайте их напишем что бы все заработало. Нам не хватает интерфейса ResponseCallback, так давайте создадим его.

Так же нам не хватает ChannelsModel, давайте и его создадим.

А еще нам не хватает ChannelsParser который парсит нашу json возвращенную с сервера. Держите, мне не жалко!

Вот! Вроде бы картинка у нас обрисовалась и все нужные классы были созданы. Теперь нам нужно все это собрать в одно, отобразить наш заветный список на экране. Разметка у нас уже готова по-этому нам осталось сделать адаптер и вызвать его в MainActivity. Вот это мы сейчас и сделаем, создаем еще один класс ChannelsAdapter и заполняем его.

Так, тут все просто я думаю все сталкивались с кастомными адаптерами по этому сильно вникать не буду. Если же не сталкивались то у меня в блоге есть статья где я описываю создание кастомного адаптера. Вернемся к функциям, в адаптере мы принимаем ArrayList с данными и отображаем его в TextView который я беру из ресурсов android’a. Собственно и все. Давайте уже наконец закончим и вызовем это все в MainActivity.

Вот так вот просто на примере можно увидеть как работают коллбеки. Но это не все, еще есть второй вариант колбеков которые работают через Setters и Getters. Я на примере этой же программы покажу как это делается, там так же ничего сложного нет.

Второй вариант Callback’a, работа через setters и getters

Как и с первым вариантом во втором я приведу абстрактный пример того как он должен выглядеть в кратце.

Интерфейс можно создавать где угодно и как угодно, по этому не обязательно его выносить в отдельный класс, можно создать как внутри активити или асинк таска так и внутри адаптера и любого другого класса. Создается интерфейс, объявляется, дальше вызывается его инстанс, то есть метод который должен отработать во время евента. А потом в Activity или Fragment’e идет вызов этого метода и получение нужных данных из него. В общем пример опять сумбурный, сейчас на примере нашей программы сделаем и будет все понятно.

Для начала в нашем адаптере нужно создать интерфейс. В самом низу класса пишем вот такое:

Дальше нам надо создать setter для этого интерфейса что бы можно было вызывать его во время создания адаптера и передавать туда наш колбек.

Теперь в getView пишем onClickListener для создания евента клика по айтему:

Вот так должен выглядеть адаптер в целом

А теперь нам нужно перенести в MainActivity этот функционал. Для этого нам нужно присвоить адаптеру новый сеттер и передать туда новый объект нашего коллбека.

В целом MainActivity должна выглядить таким образом

Вот так вот при использовании коллбеков можно достичь дзена. Надеюсь все было понятно так как пока я это писал меня двадцать пять раз отвлекли и я все эти разы терял мысль по этому возможно что то может быть черезчур запутано, спрашивайте если что то не понятно. В любом случае есть исходники рабочие, по ним так точно можно разобраться (:

Источник

Оцените статью