Привет, меня зовут Юра. И я, как и многие из вас, программист. Как известно, программисты — это не просто разработчики ПО, но создатели. Но, к сожалению, в повседневной работе сложно создавать что-то новое (особенно, когда ты занят мобильной разработкой). И это часто порождает желание собрать своего Франкенштейна (ну или велосипед, если вам так хочется), хотя бы в свободное время. Например, мне всегда хотелось сделать своего Франкенштейна, который будет выполнять за меня основную рутинную работу в Android-приложении.
И вот у меня недавно, наконец, нашлось свободное время на это дело (прим. автора: здесь можно просто за меня порадоваться)! Почитав разные статьи о том, что сейчас модно, или стало модным ещё много лет назад, я собрал для себя примерный список того, из чего будет состоять мой друг. И вот чему он у меня пока научился:
- Ходить! Он ходит в интернеты, достаёт оттуда данные, и приносит к себе
- Помнить! Если надо, он запомнит то, что взял в интернетах, может даже сперва обработать эти данные
- И вообще — выполнять несколько задач одновременно! Причём, не надо заморачиваться над тем, что вдруг наш монстрик решит, например, покувыркаться
Сколько разных элементов мне пришлось свалить в одну кучу, чтоб мой монстрик, по имени FunLib ожил! Тут собрались такие звёзды, как retrofit, eventbus, jobqueue… Но давайте по-порядку! Итак, кто за что отвечает в моём детище:
Хождение в интернет
В интернет мы ходим, используя Retrofit+OkHttp. Это позволяет делать всю работу быстро, аккуратно и при поддержке большого комьюнити. Согласитесь, очень удобно делать запрос на сервис примерно таким способом:
public interface GithubApi {
@GET("/search/repositories?sort=stars&order=desc")
SearchResult search(@Query("q") String query);
}
И ведь как круто получается, прям по-евангелистки! Ведь разработка реально ведётся не на уровне реализации, а, буквально, на уровне интерфейса! Вообще, очень много чего можно добавить в запрос, по разному настроить его. Но т.к. это не сама суть статьи, оставлю это на ваше самостоятельное изучение. Ну или было бы здорово, если бы кто-нибудь написал, как он круто использует эти библиотеки, особенно, если его ходы не тривиальны и не освещены в офф. гайде.
Память в БД
За память у него отвечает ORMLite. Как говорится, на вкус и цвет все фломастеры разные. Мне это решение нравится больше всего. Особенно, к плюсам этой библиотеки я отношу вот что:
- Из базы можно получать уже готовые объекты, а не сырой набор данных(даже с данными по вторичным ключам)
- Можно получать крусор, выполняя ORM запрос
- Можно получать курсор, выполняя обычный sql-запрос, со всеми вытекающими возможностями
- Такое решение наверняка будет легко понятно каждому, кто будет в будущем сопровождать/читать ваш код
Здесь, как обычно — аннотируем нужные классы и поля как @DatabaseTable
и @DatabaseField
, соответственно. После чего спокойно можем сложить, или, если надо, достать, данные в БД:
private void saveRepositories(List<Repository> repositories) throws SQLException {
Dao<User, ?> userDao = getDbHelper().getDao(User.class);
Dao<Repository, ?> repositoryDao = getDbHelper().getDao(Repository.class);
for (Repository repository : repositories) {
userDao.createOrUpdate(repository.getOwner());
repositoryDao.createOrUpdate(repository);
}
}
PS: к сожалению, пока FunLib не умеет удобно нотифаить лоадеры по URI… Да и его активити с фрагментами не предоставляют функционало для удобной работы с лоадерами, но всё в ваших руках! Пулл-рекввесты ждут вас. Ну или ждите, пока я это сделаю :P
Мозги для параллельной работы
Для этого немаловажного процесса был выбран инструмент под названием Priority Job Queue. Почему же мы не сделали свой собственный сервис? Да всё просто — мне было интересно использовать эту библиотеку =) Да и манифест остаётся чист. И, что не мало важно, это решение довольноприемлемо аккуратно вписывается в нашу Центральную Нервную Систему(чуть ниже про неё сказано). Но мы с FunLib сели, подумали, и решили, что тот Job, от которого команда Path предлагает нам наследоваться, слишком монструозен. Мне будет тяжело давать моему малышу какие-нибудь команды. Ну или ему будет не так просто их понять. Поэтому был сделан карапуз по имени FunJob
, который умеет просто выполнить нужную нам работу в методе public abstract T doJob() throws Throwable
.
public class SearchJob extends FunJob<List<Repository>> {
private String mQuery;
public SearchJob(int id, String query) {
super(id);
mQuery = query;
}
@Override
public List<Repository> doJob() throws Throwable {
SearchResult searchResult = ((GithubApi) getApi()).search(mQuery);
List<Repository> repositories = searchResult.getRepositories();
return repositories;
}
}
Центральная Нервная Система или просто DI
Для такой важной задачи, как доставка БД, интернета, и прочей информации в
А для отправки команды от мозгов к телу была использована штука под названием EvenBus. Изначально хотел использовать Otto, но, по непонятным причинам FunLib его невзлюбил, и я быстро отказался от него. Ну ничего — EventBus тоже отлично справляется со своей задачей! Тело всегда вовремя получает нужные команды!
Ready Steady Go!
На этом пока я решил сделать привал, завершить свой рассказ и получить от вас фитбэк. И уже после этого я продолжу дальше развивать моего кроху.
В примере вы можете отчётливо увидеть, как управлять работой FunLib — всего-то нужно:
- наследоваться от FunApp, прописать в нём путь до API, интерфейс, работающий с API и ваш класс DbHelper
- наследоваться от FunActivity/FunFragment, а там уже удобно стартовать работу, получать доступ к API и БД
- сделать то, что вам нужно! ;)
Постскриптум
Возможно, прочитав про лоадеры, вы подумаете, что я, наконец, решу прикрутить к приложению ContentProvider. Но нет, этого делать я не планирую, т.к. думаю не спроста в офф. гайде написано: You don't need to develop your own provider if you don't intend to share your data with other applications. В моей практике ещё не приходилось делать такого приложения, которые бы предоставляло данные другим приложениям. И не надо из-за этого кидать в меня помидорами! Всем нам разные задачи попадаются.
Так же пока печалит то, что нужно самостоятельно следить за тем, какой ID для FunJob был выставлен. Но ничего — это будет исправлено, и это станет очередной вкусняшкой!
Кто пропустил ссылку на репозиторий, ловите: https://github.com/senneco/FunLib
Встретимся в комментах и в пулл-реквестах :D
Автор: senneco