Comments 52
Предложенный подход не будет работать на практике: подписка Activity на AsyncTask — это наверное самая популярная джуниорская ошибка. Приводит к падениям (или зависаниям, или вообще не понятно к чему — как повезёт) при попытках перевернуть девайс в процессе выполнения сравнительно долгих операций. А чтобы от этой ошибки избавиться, нужно изобразить что-то типа habrahabr.ru/post/240543. И для предложенной красоты места там скорее всего не останется.
0
Предложенный подход заключается в реализации View классов, а не в использовании AsyncTask. В реальных проектах, конечно, его не нужно использовать для загрузки данных, тем более когда есть множество готовых решений — Robospice, Volley. На счет красоты не согласен, если с умом реализовать модельный слой и не раздувать код контроллера, то все будет ок.
+2
Я тогда наверное не понял о чём статья.
1. Статья называется «Сажаем контроллеры на диету». Т.е. про контроллеры.
2. В начале статьи сказано: «При использовании MVC в Android, Activity или Fragment является контроллером». Т.е. я в первую очередь смотрю на код Activity, потому что сказано, что «статья про контроллеры, а контроллеры — это Activity».
Посмотрел — прокомментировал. Интересно было бы посмотреть, насколько чистый код получился бы, если бы вы канонично связь model->view делали через Loader, а controller->model через IntentService. У меня есть искренние сомнения по поводу того, что от предложенного подхода в итоге что-то останется.
1. Статья называется «Сажаем контроллеры на диету». Т.е. про контроллеры.
2. В начале статьи сказано: «При использовании MVC в Android, Activity или Fragment является контроллером». Т.е. я в первую очередь смотрю на код Activity, потому что сказано, что «статья про контроллеры, а контроллеры — это Activity».
Посмотрел — прокомментировал. Интересно было бы посмотреть, насколько чистый код получился бы, если бы вы канонично связь model->view делали через Loader, а controller->model через IntentService. У меня есть искренние сомнения по поводу того, что от предложенного подхода в итоге что-то останется.
0
Через Loader'ы загрузку данных с сети тоже не делают)
А для IntentService достаточно сделать хороший уровень абстракции, всю работу с Intent'ами скрыть в отдельной сущности и, если потребуется, написать немного кода в BaseFragment или BaseActivity для автоматического подключения/отключения листенеров
А для IntentService достаточно сделать хороший уровень абстракции, всю работу с Intent'ами скрыть в отдельной сущности и, если потребуется, написать немного кода в BaseFragment или BaseActivity для автоматического подключения/отключения листенеров
+1
upd. ответили
0
А кто сказал, что Activity является контроллером, а не View, например? Этот класс решает задачи и отображения и обработки событий. Почему вам надо обязательно что-то от него оторвать?
+1
1. Если бы Activity был View тогда где контроллер?
2. Крутые ребята обычно отделяют бизнес-логику от представления
2. Крутые ребята обычно отделяют бизнес-логику от представления
+1
А зачем тащить веб-привычки в мир мобильной разработки?
Я не говорю, что логика должна быть в Activity, но изначально Гуглом сделано так, что этот класс управляет и отображением и обработкой событий. Если логики много, то она перетекает туда, где данные хранятся (модель), а отображение пусть останется тут (в отдельных коротеньких методах).
Я не говорю, что логика должна быть в Activity, но изначально Гуглом сделано так, что этот класс управляет и отображением и обработкой событий. Если логики много, то она перетекает туда, где данные хранятся (модель), а отображение пусть останется тут (в отдельных коротеньких методах).
+1
userView.hideProgressBar();
У вас контроллер практически напрямую управляет отображением, знает о прогресс-баре и видимо вообще обо всех UI-элементах?
Бизнес-логика — это изменение состояния моделей, а у вас контроллер, опять же, меняет отображение. Т.е. в одном месте и бизнес-логика и логика отображения, где разделение?
Суть MVC, как раз таки, в односторонней зависимости, а не в том, что контроллер — место встречи всех.
Отображение знает об интерфейсе контроллере (получение и установка параметров, например, через вызов методов), контроллер знает об интерфейсе модели (тоже самое), модель не знает о них ничего.
+2
Да, контроллер знает о том, что на экране можно показывать и скрывать progress bar, но он не реализует это поведение. Так же контроллер ничего не знает о UI компонентах, он работает только с интерфейсом класса View.
+1
1. Что такое «реализует поведение»? Это то чем занимается ОС, VM или драйвер видеокарты?
2. В чем отличие «userView.showProgressBar();» от «progressBar.setVisibility(View.VISIBLE);»? Дополнительный слой абстракции — это я поняла, но в чем различие вашего Activity от View, если оба управляют отображением? Так ведь можно сколько угодно слоев вводить, причем тут MVC?
2. В чем отличие «userView.showProgressBar();» от «progressBar.setVisibility(View.VISIBLE);»? Дополнительный слой абстракции — это я поняла, но в чем различие вашего Activity от View, если оба управляют отображением? Так ведь можно сколько угодно слоев вводить, причем тут MVC?
+2
1. «Реализует поведение» значит скрыть детали создания и наполнения данными View
2. Отличие в том, что Activity говорит View классу, что нужно сменить состояние экрана или заполнить его данными, а View делает это, причем реализацию метода showProgressBar можно менять для разных View, например на одном экране progress bar нужно показывать в центре экрана, для других это поведение может быть различным
2. Отличие в том, что Activity говорит View классу, что нужно сменить состояние экрана или заполнить его данными, а View делает это, причем реализацию метода showProgressBar можно менять для разных View, например на одном экране progress bar нужно показывать в центре экрана, для других это поведение может быть различным
+1
habrahabr.ru/company/redmadrobot/blog/257861/#comment_8416179
Вы не можете знать о «будущих» случаях по вашему же примеру, иначе это теряет смысл. И да showLoading — это правильное решение, теперь осталось вас убедить, что контроллер не должен вызывать этот метод у view, а должен иметь такое состояние.
Наверное, «не реализует». Однако, почему «создание и наполнение данными» — это поведение, а отображение/скрытие на экране — что-то другое, не ясно. Казалось бы, наоборот.
Теперь подумайте, ваша основная задача — отвязать класс контроллера от класса представления, чтобы контроллер можно было использовать с разными представлениями.
При этом вы упорно используете экземпляр view в классе контроллера. Т.е. противоречите себе же.
Класс вашего controller знает об интерфейсе конкретно этого класса view. Знает о его showProgressBar. Если в другом view вообще не будет showProgressBar? Если другое представление вообще никак не реализует отображение загрузки? И у него нет метода showLoading и любого подобного?
В таком случае можно сделать метод более общим, например, showLoading, и реализовывать его по-разному
Вы не можете знать о «будущих» случаях по вашему же примеру, иначе это теряет смысл. И да showLoading — это правильное решение, теперь осталось вас убедить, что контроллер не должен вызывать этот метод у view, а должен иметь такое состояние.
1. «Реализует поведение» значит скрыть детали создания и наполнения данными View
Наверное, «не реализует». Однако, почему «создание и наполнение данными» — это поведение, а отображение/скрытие на экране — что-то другое, не ясно. Казалось бы, наоборот.
2. Отличие в том, что Activity говорит View классу, что нужно сменить состояние экрана или заполнить его данными, а View делает это, причем реализацию метода showProgressBar можно менять для разных View, например на одном экране progress bar нужно показывать в центре экрана, для других это поведение может быть различным
Теперь подумайте, ваша основная задача — отвязать класс контроллера от класса представления, чтобы контроллер можно было использовать с разными представлениями.
При этом вы упорно используете экземпляр view в классе контроллера. Т.е. противоречите себе же.
Класс вашего controller знает об интерфейсе конкретно этого класса view. Знает о его showProgressBar. Если в другом view вообще не будет showProgressBar? Если другое представление вообще никак не реализует отображение загрузки? И у него нет метода showLoading и любого подобного?
+1
Главная моя задача была не отвязать контроллер от представления, а уменьшить количество кода в контроллере, путем создания слоя View классов, с чем они довольно хорошо справляются. Если вы хотите использовать разные View для одного и того же контроллера, логично что у такой View должен быть интерфейс, который она должна реализовать. У другой View не может не быть метода showProgressBar, т.к. он будет в её интерфейсе, либо если сильно хочется не показывать пользователю информацию о процессе загрузки, то реализацию метода можно оставить пустой.
+1
Главная моя задача была не отвязать контроллер от представления, а уменьшить количество кода в контроллере, путем создания слоя View классов, с чем они довольно хорошо справляются.
С чем хорошо справляются, с вынесением части кода в другой класс? Ну да, только почему вы называете это View? Назовите это ControllerPartial, а лучше ActivityPartial, ниже есть пример про region.
Это все нужно городить для того чтобы работать с абстракциями (интерфейсами) и локализовать код, который чаще всего подвергается изменениям(код представления) в отдельном классе
У другой View не может не быть метода showProgressBar, т.к. он будет в её интерфейсе, либо если сильно хочется не показывать пользователю информацию о процессе загрузки, то реализацию метода можно оставить пустой.
Т.е. если мы хотим из этой view убрать отображение загрузки — мы просто должны оставить метод пустым, так?
Теперь представим, что у нас не было этого метода изначально во view. Что мы теперь будем делать? Правильно, менять код контроллера и дописывать туда showProgressBar. И так с каждым изменением отображения…
+1
Само собой, если мы хотим убрать из View отображение progress bar'a, или установку данных с помощью showUser, то это коснется контроллера, но это будет изменение одной строчки. Если же мы захотим поменять способ отображения, то это коснется только View
0
Если же мы захотим поменять способ отображения, то это коснется только View
Это просто вынесение части логики в другое место. Вы можете точно так же создать класс ProgressBarController и в Activity вызывать ProgressBarController.show(). Тогда при изменении способа отображения прогресс-бара — activity-класс не будет меняться.
Этот паттерн называется — декомпозиция, а не MVC.
0
Тогда MVC можно назвать декомпозицей кода на модельные классы, классы представления и контроллеры. О чем и речь в статье
0
Тогда MVC можно назвать декомпозицей кода на модельные классы, классы представления и контроллеры. О чем и речь в статье
MVC — можно назвать декомпозицией, а то, о чем речь в статье — нет.
-1
Ну как же, рассказывается о контроллере, о View, тут и MVC рядом.
-2
Ну если контроллер и view — это любые классы, без классификации их смысла, просто содержащие в названии (или в мыслях) «controller» и «view», то хорошо, вы описали MVC.
0
Ок. Давайте введем некоторые термины, т.к. мы по-разному понимаем MVC
Контроллер — ловит события от пользователя (клики, свайпы и тд) и обрабатывает их, ничего не знает о том как отображать данные
View — содержит информацию как визуализировать данные, не содержит никакой логики обработки событий
Model — предоставляет данные
Что и представлено в статье. Вы хотели создать ProgressBarController, но я не могу его назвать контроллером, т.к. там нет взаимодействия с пользователем. Так же не могу создать ControllerPartial или ActivityPartial по той же причине. А вот View отличное название, т.к. все что делает этот класс это визуализирует данные и под описание контроллера никак не подходит.
Контроллер — ловит события от пользователя (клики, свайпы и тд) и обрабатывает их, ничего не знает о том как отображать данные
View — содержит информацию как визуализировать данные, не содержит никакой логики обработки событий
Model — предоставляет данные
Что и представлено в статье. Вы хотели создать ProgressBarController, но я не могу его назвать контроллером, т.к. там нет взаимодействия с пользователем. Так же не могу создать ControllerPartial или ActivityPartial по той же причине. А вот View отличное название, т.к. все что делает этот класс это визуализирует данные и под описание контроллера никак не подходит.
+2
Контроллер — ловит события от пользователя (клики, свайпы и тд) и обрабатывает их, ничего не знает о том как отображать данные
У вас контроллер прекрасно знает, что состояние loading — означает показать progressbar. Это именно как. Т.е., ваш контроллер знает из чего состоит View (в ней есть прогрессбар), а значит ваша MVC не несет никакой практической ценности, ведь отделения логики от представления нет. В одном месте хранятся знания о модели и о представлении. А так как единственная и самая главная ценность MVC именно в этом, то ваша архитектура — не MVC.
Вы хотели создать ProgressBarController, но я не могу его назвать контроллером, т.к. там нет взаимодействия с пользователем.
Ок, пусть будет TextBoxController с подпиской на onchange событие.
или ActivityPartial по той же причине
?
А вот View отличное название, т.к. все что делает этот класс это визуализирует данные и под описание контроллера никак не подходит.
View — отличное название, с этим ведь никто и не спорит, только внимание в 3 раз задаю вопрос. В чем смысл этого разделения? Я привела кучу примеров и везде требовалось изменить код вашего контроллера и view.
Вы написали, что смысл просто в вынесении части кода, но причем тут MVC?
+1
Вы считаете что MVC — это обязательно MVC с активной моделью, в которой контроллер не связан с View? В статье показан MVC с пассивной моделью когда контроллер обращается к View для его перерисовки.
0
Вы считаете что MVC — это обязательно MVC с активной моделью, в которой контроллер не связан с View?
M — модель, предметная область, бизнес-логика.
C — Промежуточное звено для уменьшения связаности.
V — Интерфейс для конечного клиента.
Собственно, весь смысл MVC (в отличии от других шаблонов) именно в контроллере и именно в уменьшении связанности.
Нет никаких правил, что именно должно быть в модели, контроллере и виде, правило одно — в этом должен быть практический смысл. А главный смысл — повторное использование и минимальные изменения частей кода при изменении тех. задания.
В статье показан MVC с пассивной моделью когда контроллер обращается к View для его перерисовки.
В статье показан пример, в котором при изменении модели нам придется менять и модель и контроллер. При изменении отображения, нам придется менять и отображение и контроллер.
Т.е. контроллер является ТТУКом, который вместо внедрения еще одного слоя для уменьшения связанности — увеличивает ее. В одном месте находится и бизнес-логика (изменение модели), и работа с интерфейсом (обработка событий), и отображение (showProgressBar).
Т.е. никакого разделения на MVC нет, все в одном классе. Зато есть вынесение части логики отображения в другой класс.
И да, пассивная модель — это когда мы модель(бизнес-логику) описываем в одном классе с контролером. Это уже тоже MVC с натяжкой, но все еще лучше, чем у вас — все три части в одном месте.
0
Тысячу раз уже обсуждали, что MVC и андроид не совместимы. Зачем гордить все это, если SDK нам предоставляет готовые компоненты приложения, которые по своей натуре малосвязны? Эта статья нормально смотрелась в 2009-2010 году, когда народ перешел из web программирования и тянул свои концепции, но сейчас-то уже обо всем догорились и пора перестать заниматься вот этим.
0
Сейчас работаю на улучшением архитектуры своих приложений. Не подскажете, что тогда юзать тру, если не MVC?
0
Следующая статья будет по MVP. Но правильное использование MVC это уже лучше чем ничего
+1
Используйте сервисы, контент провайдеры, бродкаст ресиверы и активити.
-1
Не знал, что Кэп пишет под Android) Это понятно, но как это все красиво архитектурно оформить, вот в чем вопрос. Если не MVC.
-1
И чего сразу минусовать? Я ведь согласен, что mvc на дроиде реализовывать — это оверинжиниринг. Но «как не делать mvc правильно» тоже надо уметь. И ioschedule не лучший пример, по крайней мере, за 2014 год. Подождем 2015-го, вроде не за горами.
0
Почему не лучший пример? Инженеры из команды Android показывают, как они пишут приложения — что может быть лучше?
Минус скорей всего поставили за «Кэп пишет под Android».
Минус скорей всего поставили за «Кэп пишет под Android».
0
Была когда-то статья по этому поводу: habrahabr.ru/post/241139
0
Это кстати наглядный пример убогости разработки под андроид, приложение имеет баги с восстановлением состояния и имеет столько кода внутри (под 100тыс строк xml+java), что страшно становится, а написано гуглом.
0
Это все нужно городить для того чтобы работать с абстракциями (интерфейсами) и локализовать код, который чаще всего подвергается изменениям(код представления) в отдельном классе
+1
Теперь представьте, что вместо прогресс-бара мы хотим крутить spinner или просто писать слово загрузка. В вашем примере придется менять код контроллера и код представления.
0
У вас есть статистика какой код чаще меняется? Посмотрите исходники гугловых приложений — там нет никакого MVC.
+1
UPD: я вижу вы какие-то стажировки проводите. Пожалуйста, не учите этому там!
-3
Идея хорошая, но на практике часто связь между активити и контролами слишком большая чтоб их разделять.
Я в таких случаях группирую код относящийся к разным частям с помощью регионов (//region в Android Studio).
Также отсутствие в Java ивентов и делегатов усложняет реализацию красивых интерфейсов.
Дополню пост этой древней статьей.
Я в таких случаях группирую код относящийся к разным частям с помощью регионов (//region в Android Studio).
Также отсутствие в Java ивентов и делегатов усложняет реализацию красивых интерфейсов.
Дополню пост этой древней статьей.
+1
Есть мнение, что MVC в андроиде уже есть: View — это xml-разметка, Controller — это активити, ну а Model остаётся вам на реализацию.
+3
Хочу также добавить что в Android разработке чаще используется разновидность MVC-паттерна — MVP (Model-View-Presenter).
Более подробно можно почитать о них например тут:
http://habrahabr.ru/post/215605/
http://antonioleiva.com/mvp-android/ (на английском)
http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ (на английском)
Более подробно можно почитать о них например тут:
http://habrahabr.ru/post/215605/
http://antonioleiva.com/mvp-android/ (на английском)
http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ (на английском)
0
Гугл наконец-то занялся архитектурой сам и сделал MVVM)
developer.android.com/tools/data-binding/guide.html
developer.android.com/tools/data-binding/guide.html
0
Используя androidannotations @ViewGroup/View можно вынести по крайней мере часть UI логики из активити в другой класс, но целиком избавится от UI кода в активити не получится, но по крайней можно сократить и упростить за счет аннотаций. Теперь может где-то пригодится и биндинг, но вполне может оказаться, что проще и понятнее написать геттер/сеттер во вью, чем пытаться потребить биндинг от гугла :)
Добиться какой-то более-менее похожей реализации MVC вряд ли получится из-за специфического апи андроида, когда все прибито к активити гвоздями и завязано на ее жизненный цикл.
Добиться какой-то более-менее похожей реализации MVC вряд ли получится из-за специфического апи андроида, когда все прибито к активити гвоздями и завязано на ее жизненный цикл.
0
Sign up to leave a comment.
Сажаем контроллеры на диету: Android