Ну цена parse это отдельная тема для обсуждения.
Да, я безусловно согласен, что Firebase открывает кучу возможностей.
Просто у меня на парсе был отличный проект, сейчас дорого его переносить (он без монетизации).
Свой парс не имеет клауд кода, так что это не вариант.
А так у нас парс при регистрации сам спокойно дергал апи смс шлюза и юзер получал смс для подтверждения своего номера. Это делалось в 10 строк кода без своего сервака. Жаль, что его закрыли.
Использую RetainInstance фрагменты только для сохранения объектов, которые должны пережить разворот экрана, например момент авторизации пользователя, заливка файла и прочее.
Сохраняемый объект при этом должен реализовывать паттерн Observer and Observable.
Кому интересно, пример:
ModelStorage.java
public class ModelStorage extends Fragment {
public static final String TAG = ModelStorage.class.getCanonicalName();
private CallbackModel model = new CallbackModel();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public CallbackModel getCallbackModel(){
return model;
}
CallbackModel.java
public class CallbackModel {
private CallbackObservable observable = new CallbackObservable();
...
public void runTask() {
// some work
....
observable.notifyOnSucces();
}
public void registerObserver(CallbackObserver observer) {
observable.registerObserver(observer);
}
public void unregisterObserver(CallbackObserver observer) {
observable.unregisterObserver(observer);
}
public interface CallbackObserver {
void onSucces();
void onFail();
}
private class CallbackObservable extends Observable<CallbackObserver> {
public void notifyOnSucces() {
for (CallbackObserver observer : mObservers) {
observer.onSucces();
}
}
public void notifyOnFail() {
for (CallbackObserver observer : mObservers) {
observer.onFail();
}
}
}
}
Пример использования
public class SomeFragment extends BaseFragment implements CallbackModel.CallbackObserver {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ModelStorage storage = (ModelStorage) getActivity()
.getSupportFragmentManager()
.findFragmentByTag(ModelStorage.TAG);
if (storage != null) {
model = storage.getCallbackModel();
} else {
final ModelStorage newStorage = new ModelStorage();
getActivity()
.getSupportFragmentManager()
.beginTransaction()
.add(newStorage, ModelStorage.TAG)
.commit();
}
model.registerObserver(this);
}
@Override
public void onDestroy() {
super.onDestroy();
model.unregisterObserver(this);
}
@Override
public void onSuccess() {
}
@Override
public void onFail() {
}
}
Если приложение нарушает какие-то правила Play Store и его не пропускают, это совершенно не значит, что нужно отказываться от Play Store вовсе.
Вы можете:
исправить замечания.
использовать альтернативные источники, как Вы и пишите в статье.
Аналитика, crashreports — Flurry?
Ручное автообновление приобретает смысл только, если Вы распространяете свое приложение исключительно через публикацию apk. Я бы как пользователь не понял, почему приложение, скаченное с Play (Yahho, Yandex не важно) Store вдруг перекинуло меня ан apk файл.
<string name="new_update_message" formatter=true>"Доступно обновление приложения rutracker free до версии %s - желаете обновиться? Если вы согласны - вы будете перенаправлены к скачиванию APK файла, который затем нужно будет открыть.</string>
в качестве альтернативного решения foreground-мусоровозу существует ещё такой хак: создание иконки приложения в трее, такие приложения тоже в фоне не закрываются.
Это и есть foreground-сервис. Просто этот я назвал мусоровоз, потому что в нем был мусор :)
Речь про изменение кода, а не про рабочее уже приложение. Т.е. когда человек взял и изменил что-то в коде синглтона, то он не может быть уверен в работоспособности конструкции, ибо синглтон может затрагивать множество классов во всём приложении. Это называется сильносвязанным приложением.
А когда приложение работает и там синглтон работает в стиле обсервера, когда активити подписывается и отписывается к примеру в метода onResume, onPause, то тут никаких потерь нет, ибо синглтон сам по себе инициируется класслодером, и если класслодер умирает, то умирает и процесс приложения, то значит умерли и все Activity (лишь только Task может жить).
А пардон, понял этот момент.
Но блин, разве Вы не согласны, что реальна ситуация, когда из синглтона просто возвращаются те данные, которых ты не ждешь? Какой-то сервис параллельный их сменил, хотя бы.
Вы можете мне объяснить такой момент:
«Если ты изменил этот стейт — то не факт что все потребители этого синглтона ожидают это изменение и правильно на него среагируют.» Вы отвечаете «Я полностью согласен. И я понимаю этот минус»
А если стейт изменился, потому что «несколько раз может быть инициализирован, что данные в нём теряются» — это смешной довод.
А вот с этого момента поподробнее. С чего вы решили что вы получите новый экземпляр класса?
Вот Вам пару вариантов:
1. Допустим Вы инициализировали статический Singleton в стартовой активити. Когда она будет выгружена, Вы потеряете ссылку на Singleton и получите новый инстанс.
2. Вы инициализировали статический Singleton в унаследованном от Application классе. Ваш юзер ходит по окнам и все хорошо и прекрасно. Потом ему приходит СМС и он переключается на ее чтение, а параллельно у него запущен скайп, играет музыка и в смс ему прислали ссылку, по которой он открыл браузер. Android выгружает Ваш процесс и когда юзер возвращается в приложение Вы так же получите новый инстанс.
P.S. Я не говорю, что этот паттерн можно или нельзя использовать в андроиде. Но я точно знаю, что его использование может сыграть злую шутку.
Конечно, Вы можете сказать, о том, что:
Но можно и сохранить, это ВООБЩЕ не проблема. Взяли и сохранили в том же синглтоне. Что не так?
Это и не есть проблема. Проблема в том, что вполне реально что-то не учесть.
Вот Вам и проблема синглтона для Андроида. Что делать, если мы запустили выбор файла и пока была открыта галерея наше приложение закрылось и по возвращению у нас нет сессии, перекинуть на окно логина? Круто, я в чате шлю файл другу, но вместо этого меня выкидывает из сессии. Очень крутое поведение.
Это нужно в onSaveInstanceState сохранить id сессии и при ресторе его обратно закинуть в синглтон?
Ну как Вам сказать. Это мое личное мнение.
Вы же понимаете, что в приложениях для Android абсолютно нормально при очередном вызове getInstance() получить новый экземпляр класса? К этому нужно быть готовым.
Да, я безусловно согласен, что Firebase открывает кучу возможностей.
Просто у меня на парсе был отличный проект, сейчас дорого его переносить (он без монетизации).
Свой парс не имеет клауд кода, так что это не вариант.
А так у нас парс при регистрации сам спокойно дергал апи смс шлюза и юзер получал смс для подтверждения своего номера. Это делалось в 10 строк кода без своего сервака. Жаль, что его закрыли.
Про FireGeo почитаю.
Еще нотификацию не отправить на изменение статуса без back-end сервера
Как Вы при помощи Firebase получите список курьеров в радиусе 500 метров от себя? Всего курьеров в бд 3000000, например.
P. S. Я не говорю, что Firebase чем то плох. Я говорю только, что это не Parse.com
Кое кто спалился и кое кто с кое кем на грани развода.
Итог, сервис из коробки без back-end не подойдет для многих идей.
Автор, Вы не разбирались как, например, фильтровать данные в запросах по нескольким коллекциям?
Сохраняемый объект при этом должен реализовывать паттерн Observer and Observable.
Кому интересно, пример:
Google self-driving bicycle
Скрин http://s018.radikal.ru/i503/1604/ba/00f8378d66bd.png
Если приложение нарушает какие-то правила Play Store и его не пропускают, это совершенно не значит, что нужно отказываться от Play Store вовсе.
Вы можете:
Аналитика, crashreports — Flurry?
Ручное автообновление приобретает смысл только, если Вы распространяете свое приложение исключительно через публикацию apk. Я бы как пользователь не понял, почему приложение, скаченное с Play (Yahho, Yandex не важно) Store вдруг перекинуло меня ан apk файл.
Отдельно автору ссылка https://google.github.io/styleguide/javaguide.html. У Вас есть проблемы с оформлением кода. Например нельзя использовать UpperCamelCase для названия методов.
Или имя пакета Вашего приложения должно было бы быть таким ru.jehy.rutrackerfree, но никак не ru.jehy.rutracker_free.
Однако, например, в циклах стоит использовать StringBuilder, как правильно подметил jehy
Но лично я бы написал вообще так:
И ресурс строковый
Пишите приложения правильно
Это и есть foreground-сервис. Просто этот я назвал мусоровоз, потому что в нем был мусор :)
А пардон, понял этот момент.
Но блин, разве Вы не согласны, что реальна ситуация, когда из синглтона просто возвращаются те данные, которых ты не ждешь? Какой-то сервис параллельный их сменил, хотя бы.
«Если ты изменил этот стейт — то не факт что все потребители этого синглтона ожидают это изменение и правильно на него среагируют.» Вы отвечаете «Я полностью согласен. И я понимаю этот минус»
А если стейт изменился, потому что «несколько раз может быть инициализирован, что данные в нём теряются» — это смешной довод.
Как так??
Вот Вам пару вариантов:
1. Допустим Вы инициализировали статический Singleton в стартовой активити. Когда она будет выгружена, Вы потеряете ссылку на Singleton и получите новый инстанс.
2. Вы инициализировали статический Singleton в унаследованном от Application классе. Ваш юзер ходит по окнам и все хорошо и прекрасно. Потом ему приходит СМС и он переключается на ее чтение, а параллельно у него запущен скайп, играет музыка и в смс ему прислали ссылку, по которой он открыл браузер. Android выгружает Ваш процесс и когда юзер возвращается в приложение Вы так же получите новый инстанс.
P.S. Я не говорю, что этот паттерн можно или нельзя использовать в андроиде. Но я точно знаю, что его использование может сыграть злую шутку.
Конечно, Вы можете сказать, о том, что:
Это и не есть проблема. Проблема в том, что вполне реально что-то не учесть.
Это нужно в onSaveInstanceState сохранить id сессии и при ресторе его обратно закинуть в синглтон?
Позвольте полюбопытствовать, как? Поделитесь опытом.
В целом не буду с Вами спорить, на вкус и цвет все фломастеры разные.
Вы же понимаете, что в приложениях для Android абсолютно нормально при очередном вызове getInstance() получить новый экземпляр класса? К этому нужно быть готовым.