Closed Sum41forever closed 6 years ago
如果想复用依赖关系比较复杂的 Presenter, 可以选择复用该 Presenter 的 Module 和 Component, 因为 Module 和 Component, 描述了该 Presenter 的依赖关系图, 指导了 Dagger 如何去完成注入
如果acticity和fragment间的复用会不会有问题, @FragmentScope /@ActivityScope
@h2uan3g make编译都不会通过,我也不知如何复用带@FragmentScope /@ActivityScope注入的类 ,,,
这里假设新建UserDetailActivityActivity复用UserPresenter UserDetailActivityComponent的代码如下
@ActivityScope @Component(modules = {UserDetailActivityModule.class,UserModule.class}, dependencies = AppComponent.class) public interface UserDetailActivityComponent { void inject(UserDetailActivityActivity activity); @Component.Builder interface Builder { @BindsInstance UserDetailActivityComponent.Builder view(UserDetailActivityContract.View view); //名字随便 @BindsInstance UserDetailActivityComponent.Builder view2(UserContract.View view); UserDetailActivityComponent.Builder appComponent(AppComponent appComponent); UserDetailActivityComponent build(); } }
UserDetailActivityActivity的代码如下
public class UserDetailActivityActivity extends BaseActivityimplements UserDetailActivityContract.View,UserContract.View {//这里实现UserContract.View的接口 @Inject UserPresenter userPresenter; @Inject RxPermissions mRxPermissions; @Override public void setupActivityComponent(@NonNull AppComponent appComponent) { DaggerUserDetailActivityComponent //如找不到该类,请编译一下项目 .builder() .appComponent(appComponent) .view(this) .view2(this)//别忘了注入UserContract.View .build() .inject(this); } @Override public int initView(@Nullable Bundle savedInstanceState) { return R.layout.activity_user_detail; //如果你不需要框架帮你设置 setContentView(id) 需要自行设置,请返回 0 } @Override public void initData(@Nullable Bundle savedInstanceState) { userPresenter.requestUsers(true); } @Override public void showLoading() { } @Override public void hideLoading() { } @Override public void showMessage(@NonNull String message) { checkNotNull(message); ArmsUtils.snackbarText(message); } @Override public void launchActivity(@NonNull Intent intent) { checkNotNull(intent); ArmsUtils.startActivity(intent); } @Override public void killMyself() { finish(); } @Override public void startLoadMore() { } @Override public void endLoadMore() { } @Override public Activity getActivity() { return this; } @Override public RxPermissions getRxPermissions() { return mRxPermissions; } }
@buyaomiege 你编译能通过,但是在inject的时候必须传两个实现view,不然dagger初始化都不过
@buyaomiege 在activity里
@buyaomiege 在activity里
能够具体说明一下上面代码怎么修改吗,谢谢。
关于 @FragmentScope /@ActivityScope 这里统一回复:
重用同一个 Presenter,最简单的方式就是 Fragment 也使用和 Activity 一样的 Component,如果 Fragment 有自己独立的 Component,并且 Component 的 scope 和要重用的 Presenter 的 scope 不同肯定会报错。
有时候不要纠结 ActivityScope,Scope 的作用只是保证 Module 和 Component 同步。
也就是说,如果 Component 的 Scope 和 Module 的 Scope 是一样,第二次调用,就不会生成新的对象,也就是说,你 Fragment 的 Component 用 ActivityScope 也是可以的,但只要保证 Presenter 也是用的 ActivityScope 就可以了,达到的效果和用 FragmentScope 没有任何区别,所以你的 Presenter 本身用的就是 ActivityScope,你在 Fragment 中想重用这个 Presenter,那给 Fragment 的 Component 和 Module 定义 ActivityScope 也是可以的。
自定义的 Scope 本来也就没什么实际意义,就是为了在阅读源码时好区分业务层的逻辑,但是在 Dagger 编辑器中和官方定义的 @Singleton 都是使用相同的处理逻辑,核心在于 Module 和 Component 是否是同一个 scope,至于这个 scope 是什么 scope,不是太重要。
hah哈哈,我也之前还一直纠结ActivityScope 和FragmentScope ,你这么一讲,我想到多建的P层类好委屈
1、以上讨论的复用是指,一个Activity/fragment 对应多个Presenter,如果反过来呢一个Presenter对应多个Activity(虽说,这样设计并不合适)? 2、一般我理解,mvp中Presenter复用,应该是可以切换不同的view层acitivity(Presenter多个实例对应不同v层),但貌似试了几种也不行
后来试了这样直接复用component,来实现复用Presenter ,在component 多加 inject,每次调用就会生成一个新的presenter实例。这样也ok
ps: 觉得模板类生成的Presenter类的上面添加 单例scope(@FragmentScope)并没有什么用哈
你好,我也是关于一些代码复用的问题。我的项目是用的kotlin,androidx(如果需要集成很多第三方库不建议切换到Androidx,很多库还没适配)。 项目中有一些公共的接口我想把它们放在一起,不希望在每个使用的地方再写一遍重复的内容。 我尝试参考上面提到的第一种方式复用代码 在CommonModule.kt
@Module
class CommonModule(private val view: CommonContract.View) {
@ActivityScope
@Provides
fun provideCommonView(): CommonContract.View {
return view
}
@ActivityScope
@Provides
fun provideCommonModel(model: CommonContract.Model): CommonContract.Model {
return model
}
}
在LoginComponent.kt
@ActivityScope
@Component(
modules = [LoginModule::class, CommonModule::class],
dependencies = [AppComponent::class]
)
interface LoginComponent {
fun inject(activity: LoginActivity)
}
重新make project之后 在DaggerLoginComponent.java中是这样的
/**
* @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
*/
@Deprecated
public Builder commonModule(CommonModule commonModule) {// 为什么这里是会这样??没有赋值
Preconditions.checkNotNull(commonModule);
return this;
}
在LoginActivity.kt中
// 如果这两行去掉项目编译通过 生成DaggerLoginComponent.java 但commonModule()方法里面没有赋值 为何
//如果不去这两行项目直接编译不通过 不会生成DaggerLoginComponent.java 报错信息为 LoginComponent.java:8: 错误: [Dagger/DependencyCycle] Found a dependency cycle: 为何?
//@Inject
//lateinit var mCommonPresenter:CommonPresenter
override fun setupActivityComponent(appComponent: AppComponent) {
DaggerLoginComponent //如找不到该类,请编译一下项目
.builder()
.appComponent(appComponent)
.loginModule(LoginModule(this))
.commonModule(CommonModule(this))
.build()
.inject(this)
}
🙏望回复 谢谢
关于的Presenter复用,经过几天的折腾终于实现了
实测编译通过,Presenter调用正常
复用有2种方式。
复用通用的 Module
UserActivity 中注入通用 P
通用的 P 命名为 GirlPresenter, 逻辑就是发起一个请求 UserComponent 中要多添加一个通用的 Module
GirlModule 提供通用的 P 需要的对象
GirlPresenter
GirlContract
Model 的实现基本和 DEMO 中 UserModel 相同这里就不多写了
GirlPresenter 测试情况
通用的 P 发起请求并且成功回调
使用依赖 Component 的方式重用 Component
2 个 P 的回调方法都调用了的,这里就不截图了。 因为用了不同的Component,Scope 不能相同!!!带了 Scope 以后,Module,Model 等都需要新的 Scope,这就不是很方便。个人认为维护和阅读都不是很舒服,你想想一个 Acitivity 里面基类的主 Presenter 的 Scope 是一个,通用的 Presenter 的 Scope 是一个,感觉生命周期可能会出问题,这一点没深入研究,只提出自己的想法,欢迎讨论。