DroidParts — библиотека для Android 8-in-1

в 12:40, , рубрики: android development, dependency injection, orm, Разработка под android, метки: , ,

Этой статьёй я открываю цикл, посвящённый разработке Android-приложений. Но не типичных для Google Play, написанных, очевидно, задней левой mНогой, а приложений корректных и элегантных. В этом деле нам поможет DroidParts — швейцарский нож Android-библиотек с 8 лезвиями:
DroidParts — библиотека для Android 8 in 1

  1. Dependency Injection: инициализация системных и собственных зависимостей;
  2. Object-Relational Mapping для SQLite: CRUD-операции «из коробки»;
  3. Поддержка Fragments, ActionBarSherlock;
  4. Простая (де-)сериализация JSON;
  5. AsyncTasks, IntentService с обработкой Exсeptions;
  6. RESTful HTTP client с поддержкой JSON;
  7. L.og без указания тега, конфигурируемый через AndroidManifest;
  8. Утилиты типа асинхронного http-загрузчика с кешированием, View- и Intent-помощников.

Буквально час назад* увидела свет первая версия библиотеки, но сначала…

Долгое время я был приверженцем олдскульного подхода с кодом в стиле:

private Button btn;

onCreate(Bundle b) {
	super.onCreate(b);
	btn = (Button)findViewById(R.id.btn);
}

До тех пор, пока не поучаствовал в проекте, использовавшем RoboGuice. И после:

@­InjectView
private Button btn;

добровольного возврата назад не было.

С другой стороны, RoboGuice нервировал размером и всё никак не зарелизенной версией 2.0 с поддержкой Fragments. А ещё, для ORM нужна была сторонняя библиотека. И Gson для упрощения работы с JSON. Неправильно это, тянуть зависимостей на несколько размеров приложения.

В общем, следуя принципу "if you want something done right, do it yourself", я приступил just for fun.

То, что из этого получилось, доступно в версии 0.5 по адресу github.com/yanchenko/droidparts и состоит из:

  • base — DI, ORM, Activities и прочие ключевые компоненты;
  • extra — опциональные RESTful клиент и различные утилиты;
  • support-actionbarsherlock — поддержка Fragments, ActionBar и табов в связке с умолчательным ActionBarSherlock;
  • sample — «образцовое» приложение.

С рассмотрения последнего мы и приступим.

Для начала делаем git clone github.com/yanchenko/droidparts.git и импортируем Eclipse-проекты из base, extra, sample.
Первые два из них — библиотеки (Android library project).
В project.properties последнего, который полноценное приложение, обратите внимание на строку proguard.config=../proguard.cfg, указывающую на видоизменённый конфиг обфускатора, используемый при экспорте в .apk.

Хотя DroidParts содержит кастомное org.droidparts.Application, наследовать от него имеет смысл только в случае, если инъекция нужна в самом Application. Для простого приложения такой необходимости нет. Зато нужна инъекция собственных зависимостей.
В AndroidManifest.xml строка:

<meta-data android:name="droidparts_dependency_provider" android:value=".DependencyProvider" />

деклариует класс, наследующий org.droidparts.inject.AbstractDependencyProvider и являющийся фабрикой (factory) необходимых нам объектов.

Схема простая: каждый метод DependencyProvider'a возвращает instance одного из классов, доступных к инъекции. Поддерживаются два типа методов: вызываемые без параметров и с единственным параметром Context. В случае, когда инъекция производится в Activity, передаваемый Context будет именно ей, что важно для зависимостей, связанных с UI.

Примеры в коде, в т.ч. каким образом реализуются одиночки (singletons, ахаха, обожаю термины в переводе), можно посмотреть непосредственно в org.droidparts.sample.DependencyProvider.
Для инъекции системных ресурсов и сервисов дополнительные методы, естественно, не нужны.

Сама инъекция производится для полей, аннотированных @­Inject... при вызове одного из методов Injector.get().inject(...). Ручной вызов можно пропускать, наследуя от Activity, Service и т.д. из org.droidparts.
В приложении org.droidparts.sample.activity.EntryListActivity — пример такого подхода.
Обратите внимание на:

	@Override
	public void onPreInject() {
		setContentView(R.layout.activity_entry_list);
	}

Все вызовы в onCreate(...) произойдут после того, как Injector завершит работу. В данном случае это привело бы к ненайденным Views.

На этой сумбурной недосказанности я и завершаю вводную статью. Примеры DI, ORM и JSON-сериализации, достаточные, чтобы начать использовать библиотеку, есть в приложении. Подробное рассмотрение и best practices — тема для дальнейших статей.
В ближайшее время я расскажу, чем можно заменить собственные конструкторы для Activity (hint: в приложении этот паттерн есть).

На вопросы отвечу здесь или там: stackoverflow.com/questions/tagged/droidparts.

Спасибо, и пожалуйста, пишите меньше кода! (:

* по состоянию на вчерашний вечер.

Автор: yanchenko

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js