Ric*_*oth 2 android android-service android-service-binding mosby
I am creating a small app using Mosby.
The app has a service which I want to bind to. I guess the correct place to do this is in the presenter. But I can't really figure out how to do it.
What I want to archive is when the service is bound I want to call a method on it and push that value to the view, so that the state right now is correct.
When the service sends updates on the event bus I want to push that to the view as well.
我在后面的部分找到了一些例子,但没有关于如何在演示者中绑定/取消绑定服务。
我的尝试是在活动中创建这样的东西:
@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);
}
});
Run Code Online (Sandbox Code Playgroud)
然后在演示者中做这样的事情:
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?
}
Run Code Online (Sandbox Code Playgroud)
我在正确的道路上吗?这样做的正确方法是什么?我如何将值从服务发送到 onServiceConnected 中的视图,以及当我在 onEventInitialized 中的事件总线上获取事件时?
在我们深入研究可能的实现之前,需要注意以下几点:
ServiceHandler,Activity则会出现内存泄漏,因为它ServiceHandler是在您的 Activity 中实例化的 annonaymous 类,因此具有对外部 Activity 实例的引用。为避免这种情况,您可以使用您的Application类作为上下文来调用bindService()和unbindService()。MyServiceInteractor。detachView()。虽然这样做有效,但 Presenter 现在对业务逻辑内部及其工作方式有了一些明确的了解。一个更类似于 Rx 的解决方案是将服务连接的生命周期与 Rx Observable 的“生命周期”联系起来。这意味着,一旦 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()})
);
}
}
Run Code Online (Sandbox Code Playgroud)
所以基本上MyServiceInteractor.getObservable()创建了一个通往 Rx Observable 世界的桥梁,并在 observable get 取消订阅时停止服务连接。请注意,此代码片段可能无法编译。这只是为了说明可能的解决方案/工作流程的样子。
那么你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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以这里的主要问题/问题不是非常特定于 MVI 或 MVP 或 MVVM,主要是我们如何将 android Service 回调“包装”到 RxJava observable 中。一旦我们有了这个,剩下的就很容易了。
唯一与 MVI 相关的事情是连接点:视图实际上必须触发一个意图来启动服务连接。这样做是在bindIntents()通过myView.startLoadingIntent()
我希望这有帮助。
| 归档时间: |
|
| 查看次数: |
632 次 |
| 最近记录: |