Странное поведение LiveData? - PullRequest
0 голосов
/ 06 мая 2018

Я пытаюсь реализовать архитектуру MVVM, используя ViewModel и LiveData. Эти два метода находятся внутри Activity:

 private void handleResult(BoardViewModel vm) {
        vm.getLiveDataSingleObj("Result").observe(this, new Observer<Object>() {
            @Override
            public void onChanged(@Nullable Object resultObj) {
                Result result = (Result) resultObj;
                if (!result.isCompleted()) return;
                gotoResult();
            }
        });
    }

И

private void gotoResult() {
        Log.w(LOG_TAG, "Result: Moving to next activity");
        Intent intent = new Intent(boardActivity, ResultActivity.class);
        intent.putExtra("LEVEL", levelIndex);
        intent.putExtra("MAP", mapIndex);
        startActivity(intent);
    }

Метод handleResult настроен на прослушивание объектов результата, которые указывают, что игра завершилась, и пришло время перейти к следующему действию («gotoResult»). Однако это полностью нарушает навигацию в приложении, когда я возвращаюсь и говорю, что пытаюсь начать новую игровую сессию, я вместо этого сразу же перехожу к следующему действию, сообщая мне, что я уже выиграл.

Любые идеи о том, почему он запускается несколько раз и в конце концов останавливается, позволяя мне начать новый сеанс. Чтобы уточнить, если я удаляю gotoResult, логика работает каждый раз, когда нет ошибок с индексами за пределами границ или чем-то еще, только когда я добавляю goto, все ломается.

ViewModel:

private void setupHashTypes() {
        hashLiveData.put(KEY_BOARD, liveDataBoardQuery);
        hashLiveData.put(KEY_STEPS_COUNTER, game.getStepsTakenLiveData());
        hashLiveData.put(KEY_PATH_CHANGE, game.getPathChangedLiveData());
        hashLiveData.put(KEY_VALUE_CHANGE, game.getValueChangeLiveData());
        hashLiveData.put(KEY_TIMER, game.getTimerLiveData());
        hashLiveData.put(KEY_SELECTED, game.getSelectedLiveData());
        hashLiveData.put(KEY_DESELECTED, game.getDeselectedLiveData());
        hashLiveData.put(KEY_HOLD, game.getHoldLiveData());
        hashLiveData.put(KEY_UNHOLD, game.getUnholdLiveData());
        hashLiveData.put(KEY_RESULT, game.getResultLiveData());
    }

    public LiveData<Object> getLiveDataSingleObj(String type) {
        if (hashLiveData.containsKey(type)) {
            return (LiveData<Object>) hashLiveData.get(type);
        }
        throw new IllegalArgumentException("Invalid: key was not found: " + type);
    }

А у модели есть геттеры, пример:

  private final SingleLiveEvent<Result> resultLiveData = new SingleLiveEvent<>();
    public LiveData<Result> getResultLiveData() {
        return resultLiveData;
    }

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Переход от MutableLiveData, которая всегда пересылает предыдущие заданные значения новым подписчикам, к SingleLiveEvent, который не имеет такого поведения, решил проблему.

Класс можно найти здесь: https://github.com/googlesamples/android-architecture/tree/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp

0 голосов
/ 06 мая 2018

вы должны удалить наблюдателя в onDestroy() методе

...