Этой статьёй я открываю цикл, посвящённый разработке Android-приложений. Но не типичных для Google Play, написанных, очевидно, задней левой mНогой, а приложений корректных и элегантных. В этом деле нам поможет DroidParts — швейцарский нож Android-библиотек с 8 лезвиями:
- Dependency Injection: инициализация системных и собственных зависимостей;
- Object-Relational Mapping для SQLite: CRUD-операции «из коробки»;
- Поддержка Fragments, ActionBarSherlock;
- Простая (де-)сериализация JSON;
- AsyncTasks, IntentService с обработкой Exсeptions;
- RESTful HTTP client с поддержкой JSON;
- L.og без указания тега, конфигурируемый через AndroidManifest;
- Утилиты типа асинхронного 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 завершит работу. В данном случае это привело бы к ненайденным View
s.
На этой сумбурной недосказанности я и завершаю вводную статью. Примеры DI, ORM и JSON-сериализации, достаточные, чтобы начать использовать библиотеку, есть в приложении. Подробное рассмотрение и best practices — тема для дальнейших статей.
В ближайшее время я расскажу, чем можно заменить собственные конструкторы для Activity
(hint: в приложении этот паттерн есть).
На вопросы отвечу здесь или там: stackoverflow.com/questions/tagged/droidparts.
Спасибо, и пожалуйста, пишите меньше кода! (:
* по состоянию на вчерашний вечер.
Автор: yanchenko