我正在使用Mosby创建一个小应用程序。
该应用有一项我想要绑定的服务。我想在演示者中这样做的正确位置。但我无法弄明白该怎么做。
我想要存档的是绑定服务时我想在其上调用一个方法并将该值推送到视图,以便现在的状态是正确的。
当服务在事件总线上发送更新时,我想将其推送到视图中。
我在后面的部分找到了一些示例,但没有关于如何在演示者中绑定/取消绑定服务的内容。
我的努力就是在活动中创建这样的东西:
@NonNull
@Override
public MyPresenter createPresenter() {
return new MyPresenter(new MyService.ServiceHandler() {
@Override
public void start(ServiceConnection connection) {
Intent intent = new Intent(MyActivity.this, MyService.class);
startService(intent);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
public void stop(ServiceConnection connection) {
unbindService(connection);
}
});
然后在演示者中做这样的事情:
private ServiceConnection connection;
private boolean bound;
private MyService service;
public MyPresenter(MyService.ServiceHandler serviceHandler) {
super(new MyViewState.NotInitialiezedYet());
this.serviceHandler = serviceHandler;
connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MyService.LocalBinder binder = (MyService.LocalBinder) service;
service = binder.getService();
bool isInitialized = service.isInitialized();
// how do i push isInitialized to view?
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
}
@Override
public void attachView(@NonNull SplashView view) {
super.attachView(view);
serviceHandler.start(connection);
bound = true;
}
@Override
public void detachView(boolean retainInstance) {
super.detachView(retainInstance);
if(bound) {
serviceHandler.stop(connection);
bound = false;
}
}
@Override
protected void bindIntents() {
//Not sure what this would look like?
}
public void onEventInitialized(InitializedEvent event) {
//how do I push this to the view?
}
我在正确的道路上吗?这样做的正确方法是什么?我如何将服务中的值发送到onServiceConnected中的视图,以及何时在onEventInitialized中获取事件总线上的事件?
答案 0 :(得分:4)
在深入研究可能的实施之前需要注意的一些事项:
ServiceHandler
中创建Activity
,则会导致内存泄漏,因为ServiceHandler
是在Activity中实例化的annonaymous类,因此具有对外部Activity实例的引用。为避免这种情况,您可以使用Application
类作为上下文来调用bindService()
和unbindService()
。MyServiceInteractor
。detachView()
中完成了该操作。虽然这有效,但Presenter现在对业务逻辑内部及其工作方式有一些明确的了解。更符合Rx的解决方案是将服务连接的生命周期与“生命周期”联系起来。一个Rx Observable。这意味着,一旦取消订阅/处置可观察量,就应该关闭服务连接。这也与1完美匹配。" Presenter在屏幕方向改变后生存下来" (并在屏幕方向更改期间保持可观察的订阅活动)。Observable.create()
。话虽如此,让我们看看可能的解决方案是什么样的(伪相似的代码,可能无法编译):
public class MyServiceInteractor {
private Context context;
public MyServiceInteractor(Context context) {
this.context = context.getApplicationContext();
}
public Observable<InitializedEvent> getObservable() {
return Observable.create(emitter -> {
if (!emitter.isDisposed()) {
MyService.ServiceHandler handler = new MyService.ServiceHandler() {
@Override public void start(ServiceConnection connection) {
Intent intent = new Intent(context, MyService.class);
context.startService(intent);
context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override public void stop(ServiceConnection connection) {
context.unbindService(connection);
}
};
emitter.onNext(handler);
emitter.onComplete();
}
}).flatMap(handler ->
Observable.create( emitter -> {
ServiceConnection connection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name, IBinder service) {
MyService.LocalBinder binder = (MyService.LocalBinder) service;
MyService service = binder.getService();
boolean isInitialized = service.isInitialized();
if (!emitter.isDisposed())
emitter.onNext(new InitializedEvent(isInitialized));
}
@Override public void onServiceDisconnected(ComponentName name) {
// you may want to emit an event too
}
};
})
.doOnDispose({handler.stop()})
);
}
}
所以基本上MyServiceInteractor.getObservable()
创建了一个到Rx Observable世界的桥梁,并在observable得到取消时停止服务连接。请注意,此代码段可能无法编译。它仅用于说明可能的解决方案/工作流程的外观。
然后你的Presenter
看起来像这样:
public class MyPresenter extends MviBasePresenter<MyView, InitializedEvent> {
private MyServiceInteractor interactor;
public MyPresenter(MyServiceInteractor interactor){
this.interactor = interactor;
}
@Override
void bindIntents(){
Observable<InitializedEvent> o = intent(MyView::startLoadingIntent) // i.e triggered once in Activity.onStart()
.flatMap( ignored -> interactor.getObservable() );
subscribeViewState(o, MyView::render);
}
}
所以这里的主要问题/问题不是MVI或MVP或MVVM特定的,它主要是我们如何&#34;包装&#34; android服务回调到RxJava observable。 一旦我们有了这个,其余的应该很容易。
唯一与MVI相关的是连接点:视图实际上必须触发启动服务连接的意图。这是通过bindIntents()
myView.startLoadingIntent()
中完成的
我希望有所帮助。