Как стать автором
Обновить

Использование паттерна mediator для переключения между activity

Время на прочтение3 мин
Количество просмотров7.6K


В простейшем случае для запуска Activity в Android нужно создать Intent c указанием класса вызываемого activity и Bundle из параметров. И всё хорошо, пока у нас в приложении пара экранов. Сложности начинаются тогда, когда количество экранов в нашем приложении будет исчисляться десятками. В данной статье я бы хотел предложить относительно несложный способ организации работы с большим количеством Activity.


Введение

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

  • Список документов DocumentsList. Может запускаться либо без параметров для вывода всех документов, либо с параметром int categoryId для вывода документов из данной категории;
  • Просмотр документа DocumentView. Вызывается только с параметром UUID documentId для просмотра существующего документа;
  • Редактор документа DocumentEdit. Вызывается без параметра для создания нового документа или с параметром UUID documentId для редактирования уже существующего документа.


Проблема

Что является главным недостатком стандартного подхода, при котором экземпляры Intent создаются прямо в коде Activity. Это дублирование кода. Если мы захотим добавить к вызову активити ещё один параметр, нам придётся изменить все места, где это активити вызывается. Если приложение разрабатывается более чем одним человеком, то придётся оповестить всю команду о сделанных изменениях. Если потребуется заменить одно активити другим, потребуется опять-таки искать все вхождения. И пускай такую работу за нас может выполнить IDE, все равно это не фен-шуй.

Решение

Итак, хотелось бы получить некий объект, позволяющий:
  • вызывать активити без явного указания класса вызываемого активити и без явного создания Intent;
  • подменить одно активити другим;
  • изменить параметры вызова существющего активити.

Под это описание подходит паттерн mediator. Теперь дело за реализацией.

Реализация

Диаграмма классов приведена в начале статьи. Сначала рассмотрим каждый из классов подробнее.

Класс MyIntent хранит константы для параметров вызова activity.

public class MyIntent extends Intent {
	public static final String EXTRA_CATEGORY_ID = "CategoryId";
	public static final String EXTRA_DOCUMENT_ID = "DocumentId";
}


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

public class ActivityMediator {
	
	private Activity mActivity;
	
	public ActivityMediator(Activity activity){
		mActivity = activity;
	}
	
	protected void startActivity(Class<?> cls){
		Intent intent = new Intent(mActivity, cls);
		mActivity.startActivity(intent);
	}
	
	protected void startActivity(Class<?> cls, Bundle extras){
		Intent intent = new Intent(mActivity, cls);
		intent.replaceExtras(extras);
		mActivity.startActivity(intent);
	}

}


От класса ActivityMediator наследуем класс MyActivityMediator.

public class MyActivityMediator extends ActivityMediator {

	public MyActivityMediator(Activity activity){
		super(activity);
	}

	public void showDocumentsList(){
		startActivity(DocumentsListActivity.class);
	}

	public void showDocumentsList(int categoryId){
		Bundle bundle = new Bundle();
		bundle.putInt(MyIntent.EXTRA_CATEGORY_ID, categoryId);
		startActivity(DocumentsListActivity.class, bundle);
	}

	public void showDocumentViewer(UUID documentId){
		Bundle bundle = new Bundle();
		bundle.putString(MyIntent.EXTRA_DOCUMENT_ID, documentId.toString());
		startActivity(DocumentViewActivity.class, bundle);
	}

	public void showDocumentEditor(){
		startActivity(DocumentEditActivity.class);
	}

	public void showDocumentEditor(UUID documentId){
		Bundle bundle = new Bundle();
		bundle.putString(MyIntent.EXTRA_DOCUMENT_ID, documentId.toString());
		startActivity(DocumentEditActivity.class, bundle);
	}

}


Класс MyActivity — абстрактный, от него наследуются все остальные активити в проекте.

public abstract class MyActivity extends Activity {
	
	private KadActivityMediator mActivityMediator = new KadActivityMediator(this);
	
	public KadActivityMediator getActivityMediator(){
		return mActivityMediator;
	}

}


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

getActivityMediator().showDocumentEditor();


а так — просмотр выбранного документа

UUID documentId = getCurrentDocumentId();
getActivityMediator().showDocumentViewer(documentId);


Заключение

В данной статье был дан пример использования паттерна mediator для организации работы со множеством activity в ОС Android. Развивая данную мысль, можно добавить вызовы startActivityForResult или вызов активити на основе action.
Теги:
Хабы:
+37
Комментарии29

Публикации

Изменить настройки темы

Истории

Работа

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн