关于Dagger2 android 动态生成Fragment的问题

其实动态创建Fragment的流程并不复杂。

1. 网络获取Fragment的个数。
2. 通过Component创建Fragment。

主要的问题在于:

1. 我想使用全局AppComponent 中的ApiService等对象
2. 我的BaseFragment默认使用了Dagger android的注入处理,导致编译失败

解决方案

1.使用@SupComponent来提供构建,将subComponent放到AppComponent中即可
2.去掉子类Fragment中对 Dagger 的使用 ,去除掉Presenter中Dagger的使用。
    Fragment中需要的对象通过在Module中setter过来。
    Presenter中需要的对象,同理也是通过Module中传递过来。

使用@SubComponent 的原因是希望可以使用AppComponent中构建的  全局对象 如:
     - ApiService 全局的网络请求
     - Repository 全局的数据库操作等。

原理:在Module中可以使用Dagger,通过注解直接获取需要对象(AppComponent中的全局对象),
并通过setter方法设置给Fragment或Presenter。

更改如下:

1. 去除了子类Fragment中Dagger2 android的注入

BaseFragment中代码如下:


@Override
public void onAttach(Context context) {
    inject();
    super.onAttach(context);
}

protected void inject() {
    //主要就是去掉这行代码
    AndroidSupportInjection.inject(this);
}

在NewsFragment 中如下处理

 @Override
protected void inject() {
//去除 Dagger 的inject 通过 newInstance() 创建 Fragment
//        super.inject();
}

2. 改变Presenter的注入方式

将原来的Dagger Inject的方式改为通过 Setter方法设置
- 改前

@Inject
NewsListContract.Presenter mPresenter;
  • 改后
NewsListContract.Presenter mPresenter;

public void setPresenter(NewsListContract.Presenter presenter) {
        this.mPresenter = presenter;
}

同理对于Fragment和Presenter中其他@Inject的对象也要使用Setter方法设置

3. 使用subComponent构建

   使用@SubComponent 的原因是希望可以使用AppComponent中构建的  全局对象 如:
      - ApiService 全局的网络请求
      - Repository 全局的数据库操作等。

NewsComponent.java

@NewsScope 
@Subcomponent(
        modules = {
                NewsListModule.class
        }
)
public interface NewsComponent {
    //想要的就是这个
    List<NewsListFragment> getFragment();
}

注意subComponent使用要有 Scope

NewsScope.java

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface NewsScope {
}

NewListModule.java


@Module
public class NewsListModule {
    //通过从Activity中构建NewsComponent时传入
    private List<NewsClassify> classifyList;

    public NewsListModule(List<NewsClassify> classifyList) {
        this.classifyList = classifyList;
    }

    @Provides
    @NewsScope
    public List<NewsClassify> provideClassifyList() {
        return classifyList;
    }

    @Provides
    @NewsScope
    List<NewsListFragment> getFragmentList(List<NewsClassify> classifyList, ApiService apiService) {
        List<NewsListFragment> fragmentList = new ArrayList<>();
        if (classifyList != null) {
            for (int i = 0; i < classifyList.size(); i++) {
                //手动创建Fragment,并设置 Presenter
                String id = classifyList.get(i).getAcId();
                NewsListFragment fragment = NewsListFragment.newInstance(id);
                fragment.setPresenter(new NewsListPresenter(apiService,id));
                fragmentList.add(fragment);
            }
        }
        return fragmentList;
    }
}

4. 在全局的AppComponent中提供 NewsComponent

subComponent ( NewsComponent ) 就是在这个地方提供用于创建。

AppComponent.java

@Singleton
@Component(modules = {
        ApplicationModule.class, //application
        DBModule.class, //db
        ActivityBindingModule.class, //activity 注册类
        AndroidSupportInjectionModule.class, //..
        RetrofitModule.class,    // 提供retrofit
        RepositoryModule.class, //仓库相关的类
        ApiServiceModule.class // ApiService 提供类
})
public interface AppComponent extends AndroidInjector<BaseApplication> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        AppComponent.Builder application(Application application);

        AppComponent build();
    }

    NewsComponent plus(NewsListModule newsListModule);

}

5. Activity中的调用方式

  • 网络获取成功后根据获取的 List <NewsClassify> newsClassifies 构建NewsListModule

  • 再调用newsComponent的getFragment就可以获取到 List <Fragment> 了

AppComponent appComponent = BaseApplication.getInstance().getAppComponent();
NewsComponent newsComponent = appComponent.plus(new NewsListModule(newsClassifies));
mFragments.addAll(newsComponent.getFragment());
mAdapter.notifyDataSetChanged();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值