Возобновить плавное преобразование в живые данные после поворота экрана

Скажем, у меня есть такая деятельность:

public class TestActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final TextView countdown = new TextView(this);
        setContentView(countdown);

        ViewModelProviders.of(this)
                .get(TestViewModel.class)
                .getCountdown()
                .observe(this, countdown::setText);
    }
}

И модель представления:

class TestViewModel extends ViewModel {
    private final LiveData<String> countdown =
            LiveDataReactiveStreams.fromPublisher(
                    Flowable.concat(
                            Flowable.just("Falcon Heavy rocket will launch in..."),
                            Flowable.intervalRange(0, 10, 3, 1, TimeUnit.SECONDS)
                                    .map(x -> String.valueOf(10 - x)),
                            Flowable.timer(1, TimeUnit.SECONDS)
                                    .map(ignored -> "Lift off!")
                    )
            );

    LiveData<String> getCountdown() {
        return countdown;
    }
}

Я хочу правильно обрабатывать поворот, поэтому, если пользователь поворачивает свое устройство, пока обратный отсчет показывает 5, я хочу, чтобы следующее значение после поворота было 5 (или 4, если второе уже истекло), просто выберите, где на самом деле должен быть обратный отсчет .

Если ракета уже взлетела, я хочу, чтобы она оставалась такой после вращения, я не хочу, чтобы обратный отсчет начинался снова.

На данный момент LiveDataReactiveStreams отменяет подписку на паузе и создает новую подписку при возобновлении, поэтому обратный отсчет перезапускается.

Я предполагаю, что мне нужно что-то изменить в моей части кода RxJava, чтобы это сработало. Есть идеи, что изменить?


person arekolek    schedule 19.11.2017    source источник


Ответы (1)


Спасибо Святославу Лебецкому на канале Android United Slack, который указал мне BehaviorSubject и BehaviorProcessor и предложил идею по как это исправить.

Я изменил свою модель просмотра на:

class TestViewModel extends ViewModel {

    private LiveData<String> countdown;

    LiveData<String> getCountdown() {
        if (countdown == null) {
            countdown = LiveDataReactiveStreams.fromPublisher(startCountdown());
        }
        return countdown;
    }

    private static Flowable<String> startCountdown() {
        final BehaviorProcessor<String> processor = BehaviorProcessor.create();
        Flowable.concat(
                Flowable.just("Falcon Heavy rocket will launch in..."),
                Flowable.intervalRange(0, 10, 3, 1, TimeUnit.SECONDS)
                        .map(x -> String.valueOf(10 - x)),
                Flowable.timer(1, TimeUnit.SECONDS)
                        .map(ignored -> "Lift off!")
        ).subscribe(processor);
        return processor;
    }
}

Таким образом, я могу запустить обратный отсчет только один раз в getCountdown, а BehaviorProcessor, созданный в startCountdown, позаботится о доставке последних и впоследствии выпущенных значений своим подписчикам (в данном случае LiveData).

Поскольку для LiveDataReactiveStreams требуется Flowable, здесь удобно использовать BehaviorProcessor вместо BehaviorSubject.

person arekolek    schedule 20.11.2017