Еще решил написать одну заметку по поводу коллбеков. Штука интересная и полезная, без нее редко когда получается что то разумное написать. По этому решил что надо будет написать пару примеров по работе с колбеками.
Для начала хочу сказать что есть разные библиотеки типа EventBus и OttoBus которые сделают всю работу за вас и еще больше сделают… Но иногда эти библиотеки сильно много делают для обычной тривиальной задачи, например вернуть респонс из AsyncTask'a или еще что-то похожее, из-за этого использовать эти библиотеки не целесообразно и достаточно написать один интерфейс и вызывать его в нужном месте по тому или иному событию. Собственно это я сегодня и хочу продемонстрировать на примере приложения.
У нас будет небольшой апп который будет тянуть список спорт. каналов через AsyncTask, парсить то что вернет сервер с помощью кастомного JsonArray и JsonObject и отдавать это все колбеком в активити для отображения в списке.
Для начала давайте сделаем небольшую настройку. Для работы с интернетом нам нужен премишен в манифесте, давайте его добавим.
AndroidManifest.xml
И сделаем разметку с списком, все будет елементарно и просто.
activity_main.xml
Все, с настройками мы закончили, теперь давайте кодить!
Первый вариант Callback'a, получение данных в Activity
Первый вариант у нас будет такой как я описал выше, он имеет вот такую архитектуру:
Это очень краткий пример того что будет происходить. Создаем интерфейс, далее в классе который нам должен что-то вернуть вызываем этот колбек что бы можно было отследить когда он выполнился, а после этого отображаем то что вернул колбек в нашей активити которая включает в себя собственно этот колбек.
Очень сумбурно, нам нужно более детальное рассмотрение этого способа по этому начну.
У вас должен уже быть создан пустой проект с MainActivity, нам она пока не понадобится, мы ее будем использовать в в самом конце.
Сейчас создайте новый класс который будет называться BackgroundTask, в этом методе у нас будет AsyncTask который у нас будет хватать json строку с удаленного сервера.
Вообще использовать AsyncTask не советую, для таких нужд есть прекрасная библотека Retrofit или Volley или еще куча разных великолепных библиотек которые делают запросы и не валятся при повороте экрана. По этому это чисто пример, так как я сделал запрос лучше не делать, повторюсь, лучше используйте готовые решения.
BackgroundTask.java
Вот как то так у нас будет работать наш AsyncTask, но пока что вам не хватает нескольких классов которые выполняют кое какую работу, давайте их напишем что бы все заработало. Нам не хватает интерфейса ResponseCallback, так давайте создадим его.
ResponseCallback.java
Так же нам не хватает ChannelsModel, давайте и его создадим.
ChannelsModel.java
А еще нам не хватает ChannelsParser который парсит нашу json возвращенную с сервера. Держите, мне не жалко!
ChannelsParser.java
Вот! Вроде бы картинка у нас обрисовалась и все нужные классы были созданы. Теперь нам нужно все это собрать в одно, отобразить наш заветный список на экране. Разметка у нас уже готова по-этому нам осталось сделать адаптер и вызвать его в MainActivity. Вот это мы сейчас и сделаем, создаем еще один класс ChannelsAdapter и заполняем его.
ChannelsAdapter.java
Так, тут все просто я думаю все сталкивались с кастомными адаптерами по этому сильно вникать не буду. Если же не сталкивались то у меня в блоге есть статья где я описываю создание кастомного адаптера. Вернемся к функциям, в адаптере мы принимаем ArrayList с данными и отображаем его в TextView который я беру из ресурсов android'a. Собственно и все. Давайте уже наконец закончим и вызовем это все в MainActivity.
MainActivity.java
Вот так вот просто на примере можно увидеть как работают коллбеки. Но это не все, еще есть второй вариант колбеков которые работают через Setters и Getters. Я на примере этой же программы покажу как это делается, там так же ничего сложного нет.
Исходники
GitHub
Второй вариант Callback'a, работа через setters и getters
Как и с первым вариантом во втором я приведу абстрактный пример того как он должен выглядеть в кратце.
Интерфейс можно создавать где угодно и как угодно, по этому не обязательно его выносить в отдельный класс, можно создать как внутри активити или асинк таска так и внутри адаптера и любого другого класса. Создается интерфейс, объявляется, дальше вызывается его инстанс, то есть метод который должен отработать во время евента. А потом в Activity или Fragment'e идет вызов этого метода и получение нужных данных из него. В общем пример опять сумбурный, сейчас на примере нашей программы сделаем и будет все понятно.
Для начала в нашем адаптере нужно создать интерфейс. В самом низу класса пишем вот такое:
ChannelsAdapter.java
Дальше нам надо создать setter для этого интерфейса что бы можно было вызывать его во время создания адаптера и передавать туда наш колбек.
ChannelsAdapter.java
Теперь в getView пишем onClickListener для создания евента клика по айтему:
ChannelsAdapter.java
Вот так должен выглядеть адаптер в целом
ChannelsAdapter.java
А теперь нам нужно перенести в MainActivity этот функционал. Для этого нам нужно присвоить адаптеру новый сеттер и передать туда новый объект нашего коллбека.
MainActivity.java
В целом MainActivity должна выглядить таким образом
MainActivity.java
Вот так вот при использовании коллбеков можно достичь дзена. Надеюсь все было понятно так как пока я это писал меня двадцать пять раз отвлекли и я все эти разы терял мысль по этому возможно что то может быть черезчур запутано, спрашивайте если что то не понятно. В любом случае есть исходники рабочие, по ним так точно можно разобраться (:
Исходники
GitHub
Для начала хочу сказать что есть разные библиотеки типа EventBus и OttoBus которые сделают всю работу за вас и еще больше сделают… Но иногда эти библиотеки сильно много делают для обычной тривиальной задачи, например вернуть респонс из AsyncTask'a или еще что-то похожее, из-за этого использовать эти библиотеки не целесообразно и достаточно написать один интерфейс и вызывать его в нужном месте по тому или иному событию. Собственно это я сегодня и хочу продемонстрировать на примере приложения.
У нас будет небольшой апп который будет тянуть список спорт. каналов через AsyncTask, парсить то что вернет сервер с помощью кастомного JsonArray и JsonObject и отдавать это все колбеком в активити для отображения в списке.
Для начала давайте сделаем небольшую настройку. Для работы с интернетом нам нужен премишен в манифесте, давайте его добавим.
AndroidManifest.xml
И сделаем разметку с списком, все будет елементарно и просто.
activity_main.xml
Все, с настройками мы закончили, теперь давайте кодить!
Первый вариант Callback'a, получение данных в Activity
Первый вариант у нас будет такой как я описал выше, он имеет вот такую архитектуру:
Это очень краткий пример того что будет происходить. Создаем интерфейс, далее в классе который нам должен что-то вернуть вызываем этот колбек что бы можно было отследить когда он выполнился, а после этого отображаем то что вернул колбек в нашей активити которая включает в себя собственно этот колбек.
Очень сумбурно, нам нужно более детальное рассмотрение этого способа по этому начну.
У вас должен уже быть создан пустой проект с MainActivity, нам она пока не понадобится, мы ее будем использовать в в самом конце.
Сейчас создайте новый класс который будет называться BackgroundTask, в этом методе у нас будет AsyncTask который у нас будет хватать json строку с удаленного сервера.
Вообще использовать AsyncTask не советую, для таких нужд есть прекрасная библотека Retrofit или Volley или еще куча разных великолепных библиотек которые делают запросы и не валятся при повороте экрана. По этому это чисто пример, так как я сделал запрос лучше не делать, повторюсь, лучше используйте готовые решения.
BackgroundTask.java
Вот как то так у нас будет работать наш AsyncTask, но пока что вам не хватает нескольких классов которые выполняют кое какую работу, давайте их напишем что бы все заработало. Нам не хватает интерфейса ResponseCallback, так давайте создадим его.
ResponseCallback.java
Так же нам не хватает ChannelsModel, давайте и его создадим.
ChannelsModel.java
А еще нам не хватает ChannelsParser который парсит нашу json возвращенную с сервера. Держите, мне не жалко!
ChannelsParser.java
Вот! Вроде бы картинка у нас обрисовалась и все нужные классы были созданы. Теперь нам нужно все это собрать в одно, отобразить наш заветный список на экране. Разметка у нас уже готова по-этому нам осталось сделать адаптер и вызвать его в MainActivity. Вот это мы сейчас и сделаем, создаем еще один класс ChannelsAdapter и заполняем его.
ChannelsAdapter.java
Так, тут все просто я думаю все сталкивались с кастомными адаптерами по этому сильно вникать не буду. Если же не сталкивались то у меня в блоге есть статья где я описываю создание кастомного адаптера. Вернемся к функциям, в адаптере мы принимаем ArrayList с данными и отображаем его в TextView который я беру из ресурсов android'a. Собственно и все. Давайте уже наконец закончим и вызовем это все в MainActivity.
MainActivity.java
Вот так вот просто на примере можно увидеть как работают коллбеки. Но это не все, еще есть второй вариант колбеков которые работают через Setters и Getters. Я на примере этой же программы покажу как это делается, там так же ничего сложного нет.
Исходники
GitHub
Второй вариант Callback'a, работа через setters и getters
Как и с первым вариантом во втором я приведу абстрактный пример того как он должен выглядеть в кратце.
Интерфейс можно создавать где угодно и как угодно, по этому не обязательно его выносить в отдельный класс, можно создать как внутри активити или асинк таска так и внутри адаптера и любого другого класса. Создается интерфейс, объявляется, дальше вызывается его инстанс, то есть метод который должен отработать во время евента. А потом в Activity или Fragment'e идет вызов этого метода и получение нужных данных из него. В общем пример опять сумбурный, сейчас на примере нашей программы сделаем и будет все понятно.
Для начала в нашем адаптере нужно создать интерфейс. В самом низу класса пишем вот такое:
ChannelsAdapter.java
Дальше нам надо создать setter для этого интерфейса что бы можно было вызывать его во время создания адаптера и передавать туда наш колбек.
ChannelsAdapter.java
Теперь в getView пишем onClickListener для создания евента клика по айтему:
ChannelsAdapter.java
Вот так должен выглядеть адаптер в целом
ChannelsAdapter.java
А теперь нам нужно перенести в MainActivity этот функционал. Для этого нам нужно присвоить адаптеру новый сеттер и передать туда новый объект нашего коллбека.
MainActivity.java
В целом MainActivity должна выглядить таким образом
MainActivity.java
Вот так вот при использовании коллбеков можно достичь дзена. Надеюсь все было понятно так как пока я это писал меня двадцать пять раз отвлекли и я все эти разы терял мысль по этому возможно что то может быть черезчур запутано, спрашивайте если что то не понятно. В любом случае есть исходники рабочие, по ним так точно можно разобраться (:
Исходники
GitHub
Первый пример, смысл использовать AsyncTask не в Активити, используем его в Активити и в методе onPostExecute() обновляем View, Callback'и не нужны будут.
ОтветитьУдалитьНу вообще нежелательно использовать классы внутри классов. Логику нужно всегда разделять, и вот как раз в этом случае нужны коллбеки которые будут возвращать результат. Советую почитать книгу Clean Code и почитать про SOLID
Удалить