基于MVP与Dagger2,如何在LocationService的onLocationChanged时向Presenter传递位置
嘿,作为同样踩过MVP+Dagger2坑的开发者,我来帮你捋捋怎么把LocationService里的位置更新传递到Presenter~你已经尝试注入EventBus的思路其实很可行,我给你补全这个方案,再提供一种更贴合MVP解耦思想的接口回调方式,按需选择:
方案一:完善你已尝试的EventBus实现
1. 确保Dagger提供单例EventBus
首先得让Service和Presenter拿到同一个EventBus实例,所以要在Dagger的Module里把EventBus配置为单例:
@Module public class AppModule { @Provides @Singleton EventBus provideEventBus() { return EventBus.getDefault(); } }
然后你的ServiceComponent要依赖这个AppModule(或者继承包含它的父组件),这样@Inject EventBus bus才能正确注入到LocationService里。
2. 定义位置事件类并发送
先创建一个专门的事件类来封装位置信息:
public class LocationUpdatedEvent { private final Location location; public LocationUpdatedEvent(Location location) { this.location = location; } public Location getLocation() { return location; } }
接着在onLocationChanged里发送这个事件:
@Override public void onLocationChanged(Location location) { currentLocation = location; // 发送位置更新事件 bus.post(new LocationUpdatedEvent(location)); }
3. 在Presenter中订阅并处理
让Presenter也注入同一个EventBus,然后在合适的生命周期里注册/注销订阅,避免内存泄漏:
public class YourPresenter implements YourContract.Presenter { @Inject EventBus bus; private YourContract.View view; public YourPresenter(YourContract.View view) { this.view = view; // 假设已通过Dagger完成EventBus注入 bus.register(this); } // 用@Subscribe注解订阅事件,指定主线程更新UI @Subscribe(threadMode = ThreadMode.MAIN) public void onLocationUpdated(LocationUpdatedEvent event) { Location newLocation = event.getLocation(); // 把位置信息传递给View更新UI,或做业务处理 view.showUpdatedLocation(newLocation); } @Override public void onDestroy() { // 必须注销订阅,防止内存泄漏 bus.unregister(this); } }
方案二:MVP风格的接口回调实现(无第三方库)
如果不想依赖EventBus,用接口回调更贴合MVP的解耦思想:
1. 定义位置更新回调接口
public interface LocationUpdateListener { void onLocationReceived(Location location); }
2. 在LocationService中持有回调(用弱引用防泄漏)
通过Dagger注入回调的弱引用,避免Service持有Presenter的强引用导致内存泄漏:
public class LocationService extends Service implements LocationListener { private LocationManager locationManager; private Location currentLocation; @Inject WeakReference<LocationUpdateListener> locationUpdateListenerRef; @Override public void onCreate() { super.onCreate(); // 初始化Dagger组件并注入 DaggerServiceComponent.create().inject(this); } @Override public void onLocationChanged(Location location) { currentLocation = location; // 检查回调是否有效,避免空指针 if (locationUpdateListenerRef != null && locationUpdateListenerRef.get() != null) { locationUpdateListenerRef.get().onLocationReceived(location); } } // 其他Service生命周期方法... }
3. 让Presenter实现回调接口
public class YourPresenter implements YourContract.Presenter, LocationUpdateListener { private YourContract.View view; public YourPresenter(YourContract.View view) { this.view = view; } @Override public void onLocationReceived(Location location) { // 处理位置信息,更新View view.showUpdatedLocation(location); } // 其他Presenter方法... }
4. 配置Dagger提供回调实例
在Service的Module里提供弱引用的回调:
@Module public class ServiceModule { private final LocationUpdateListener listener; public ServiceModule(LocationUpdateListener listener) { this.listener = listener; } @Provides WeakReference<LocationUpdateListener> provideLocationUpdateListener() { return new WeakReference<>(listener); } }
创建ServiceComponent时传入这个Module:
ServiceComponent component = DaggerServiceComponent.builder() .serviceModule(new ServiceModule(yourPresenterInstance)) .build();
关键注意事项
- 内存泄漏:不管用哪种方式,都要避免Service持有Presenter的强引用,弱引用或及时注销订阅是关键。
- 线程切换:
onLocationChanged可能在子线程执行,更新UI时要确保切换到主线程(EventBus的ThreadMode.MAIN或接口回调时用runOnUiThread/Handler)。 - Dagger作用域:确保ServiceComponent和Presenter所在组件的作用域兼容,避免注入失败。
内容的提问来源于stack exchange,提问作者Puja Singh
相关产品推荐
相关产品推荐

