Как стать автором
Обновить
9
0
Виталий @lavelas

Пользователь

Отправить сообщение
Ну цена parse это отдельная тема для обсуждения.
Да, я безусловно согласен, что Firebase открывает кучу возможностей.

Просто у меня на парсе был отличный проект, сейчас дорого его переносить (он без монетизации).

Свой парс не имеет клауд кода, так что это не вариант.

А так у нас парс при регистрации сам спокойно дергал апи смс шлюза и юзер получал смс для подтверждения своего номера. Это делалось в 10 строк кода без своего сервака. Жаль, что его закрыли.
Вот я и говорю, что с парсом не нужен был бекенд.
Про FireGeo почитаю.

Еще нотификацию не отправить на изменение статуса без back-end сервера
Облачным кодом парса при этом была возможность заложить определенную логику обработки данных.

Как Вы при помощи Firebase получите список курьеров в радиусе 500 метров от себя? Всего курьеров в бд 3000000, например.

P. S. Я не говорю, что Firebase чем то плох. Я говорю только, что это не Parse.com
Некоторым e2e не поможет
Кое кто спалился и кое кто с кое кем на грани развода.
Еще я не нашел возможности отправить push по изменению данных в бд. Для того же чата «новое сообщение от ххх».

Итог, сервис из коробки без back-end не подойдет для многих идей.
Не достойная. Фишка parse — облачный код. К сожалению в Firebase этого нет
Очень многое из статьи есть в sample codes.

Автор, Вы не разбирались как, например, фильтровать данные в запросах по нескольким коллекциям?
Это неудобно. Экземпляр приложения один, а таких фрагментом может быть много.
Использую 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 файл.

Отдельно автору ссылка https://google.github.io/styleguide/javaguide.html. У Вас есть проблемы с оформлением кода. Например нельзя использовать UpperCamelCase для названия методов.

activity.Update(lastAppVersion); // это воспринимается как статический класс у activity.

Или имя пакета Вашего приложения должно было бы быть таким ru.jehy.rutrackerfree, но никак не ru.jehy.rutracker_free.
Конкатенацию строковых литералов (типа "a" + "b" + "c") компилятор сам преобразует в StringBuilder.

Однако, например, в циклах стоит использовать StringBuilder, как правильно подметил jehy

Но лично я бы написал вообще так:

String message = String.format(getString(R.id.new_update_message), lastAppVersion);

И ресурс строковый

<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 сессии и при ресторе его обратно закинуть в синглтон?
Для восстанавливаемых данных лучше использовать retainInstance фрагменты.
1. Удобны, особенно как обсерверы

Позвольте полюбопытствовать, как? Поделитесь опытом.

В целом не буду с Вами спорить, на вкус и цвет все фломастеры разные.
Ну как Вам сказать. Это мое личное мнение.
Вы же понимаете, что в приложениях для Android абсолютно нормально при очередном вызове getInstance() получить новый экземпляр класса? К этому нужно быть готовым.
1

Информация

В рейтинге
Не участвует
Откуда
Днепр, Днепропетровская обл., Украина
Зарегистрирован
Активность