如何用Dagger2替代OnAttach向父Fragment注入监听器接口
我来帮你搞定这个Dagger2注入的问题~你现在的需求是把原来在子Fragment里手动赋值父Fragment监听器的逻辑,换成Dagger2自动注入,避免强转和手动代码,对吧?咱们一步步来调整代码:
步骤1:修改父Fragment的监听器字段为可注入
首先,把SignupMainFragment里的validateBasicListener改成用Lazy<BasicSignUp>来延迟获取实例(避免父Fragment初始化时子Fragment还没创建导致的null问题),并且加上@Inject注解:
public class SignupMainFragment extends DaggerFragment implements SignUPContract.View{ @Inject SignUPContract.Presenter signUPPresenter; @Inject Lazy<BasicSignUp> validateBasicListenerLazy; // 改用Lazy延迟获取实例 @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); return inflater.inflate(R.layout.fragment_signup, container, false); } // 当需要调用监听器方法时,通过Lazy获取实例 public void triggerBasicValidation() { validateBasicListenerLazy.get().signUpValidateBasic(); } }
步骤2:在父Fragment的Module中提供BasicSignUp实例
接下来,在SignupModule里添加一个@Provides方法,通过父Fragment的getChildFragmentManager获取子Fragment实例,并绑定到BasicSignUp接口。这里要确保子Fragment在父Fragment的布局里有对应的id(比如R.id.signup_basic_child_fragment):
public abstract class SignupModule { @FragmentScoped @Binds abstract SignUPContract.Presenter signUpPresenter(SignUPPresenter presenter); @FragmentScoped @Binds abstract SignUPContract.View signUpView(SignupMainFragment loginFragment); @FragmentScoped @Provides static BasicSignUp provideBasicSignUp(SignupMainFragment parentFragment) { SignupBasicChildFragment childFragment = (SignupBasicChildFragment) parentFragment.getChildFragmentManager() .findFragmentById(R.id.signup_basic_child_fragment); if (childFragment == null) { throw new IllegalStateException("SignupBasicChildFragment必须先添加到SignupMainFragment中"); } return childFragment; } @FragmentScoped // 把子Fragment的作用域改为和父Fragment一致 @ContributesAndroidInjector(modules = BasicModule.class) abstract SignupBasicChildFragment signupBasicChildFragment(); }
步骤3:统一子Fragment的作用域
把BasicModule里的@FragmentChildScoped替换成@FragmentScoped,确保子Fragment和父Fragment在同一个作用域内,这样Dagger能正确管理依赖:
@Module public abstract class BasicModule { @FragmentScoped @Binds abstract BasicContract.Presenter basicPresenter(BasicPresenter presenter); @FragmentScoped @Binds abstract BasicContract.View basicView(SignupBasicChildFragment loginFragment); }
步骤4:移除子Fragment中的手动赋值代码
最后,删掉SignupBasicChildFragment里onAttach方法中的手动赋值代码,现在Dagger会自动完成注入逻辑了:
public class SignupBasicChildFragment extends DaggerFragment implements BasicContract.View, BasicSignUp{ @Inject BasicContract.Presenter presenter; @Override public void onAttach(Context context) { super.onAttach(context); // 删除这行手动赋值的代码 // ((SignupMainFragment) getParentFragment()).validateBasicListener = this; } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); return inflater.inflate(R.layout.fragment_child_signupbasic, container, false); } // 实现BasicSignUp接口的方法 @Override public void signUpValidateBasic() { // 这里写你的验证逻辑 } }
为什么这样调整?
- 用
Lazy<BasicSignUp>延迟获取实例,解决了父Fragment初始化时子Fragment还未创建的时序问题。 - 通过父Fragment的FragmentManager获取子Fragment实例,既保证了实例的正确性,又避免了硬编码的强转耦合。
- 统一作用域后,Dagger可以在同一个作用域内管理父、子Fragment的依赖,确保注入的实例是同一个对象。
内容的提问来源于stack exchange,提问作者Reprator
相关产品推荐
相关产品推荐

