屏幕旋转后恢复可流动转换为实时数据
说我有这样的活动:
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 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 getCountdown() { return countdown; } }
我想正确处理旋转,所以如果用户在倒计时5时旋转他的设备,我希望旋转后的下一个值为5(如果第二个已经过去,则为4),只需在倒计时实际上应该到达的任何地方。
如果火箭已经升空,我希望它在旋转后保持这种状态,我不希望倒计时再次开始。
目前, LiveDataReactiveStreams
在暂停时取消订阅并在恢复时进行新订阅,因此重新开始倒计时。
我猜我应该在代码的RxJava部分改变一些东西才能使用。 关于改变什么的任何想法?
感谢Svyatoslav Lebeckiy在Android United Slack频道上向我指出了BehaviorSubject
和BehaviorProcessor
,并就如何解决这个问题提出了一个想法。
我将视图模型更改为:
class TestViewModel extends ViewModel { private LiveData countdown; LiveData getCountdown() { if (countdown == null) { countdown = LiveDataReactiveStreams.fromPublisher(startCountdown()); } return countdown; } private static Flowable startCountdown() { final BehaviorProcessor 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
启动倒计时一次,并且在startCountdown
创建的startCountdown
负责将最后和随后发出的值传递给其订户(在本例中为LiveData
)。
由于LiveDataReactiveStreams
需要LiveDataReactiveStreams
,因此在此处使用BehaviorProcessor
而不是BehaviorSubject
很方便。