如何使用 dagger-android 与演示者相互 link 片段?
How to mutually link fragments with presenters using dagger-android?
我想要一个提供视图(片段)和演示者的片段模块。 View 依赖于 presenter,presenter 依赖于 view,而 dagger 负责处理这些依赖关系。
我见过这种方法适用于活动和演示者,但未能将这种模式应用于片段。我想知道这是由于我的代码错误,还是 dagger 的限制。
这是我用于活动的基准代码:
主要Activity合同
public interface MainActivityContract {
interface View {
void setText(String text);
}
interface Presenter {
void attach();
}
}
主要Activity模块
@Module
public abstract class MainActivityModule {
@Binds
abstract MainActivityContract.View exampleFragment(MainActivity view);
@Binds
abstract MainActivityContract.Presenter exampleFragmentPresenter(MainActivityPresenter presenter);
}
Activity代码:
public class MainActivity extends DaggerAppCompatActivity implements MainActivityContract.View {
@Inject
MainActivityContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPresenter.attach();
}
@Override
public void setText(String text) {
((TextView) findViewById(R.id.example_text)).setText(text);
}
}
演示者代码:
public class MainActivityPresenter implements MainActivityContract.Presenter {
private MainActivityContract.View mView;
@Inject
public MainActivityPresenter(MainActivityContract.View view) {
mView = view;
}
public void attach() {
this.mView.setText("Hello world!");
}
}
普通匕首-android设置:
申请代码
public class MyApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().application(this).build();
}
}
AppComponent
@Component(modules = {ActivityBindingModule.class, AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<MyApplication> {
@Component.Builder
interface Builder {
@BindsInstance
AppComponent.Builder application(Application application);
AppComponent build();
}
}
Activity绑定模块
@Module
public abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity mainActivity();
}
现在我想将 activity 转换成片段。
重复上述模式,唯一不同的是片段代码:
public class ExampleFragment extends DaggerFragment implements ExampleFragmentContract.View {
@Inject
ExampleFragmentContract.Presenter mPresenter;
@Inject
public ExampleFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.example_fragment, container, false);
}
@Override
public void setText(String text) {
((TextView) getView().findViewById(R.id.example_text)).setText(text);
}
}
Main Activity 变笨了,演示者被删除了:
public class MainActivity extends DaggerAppCompatActivity {
@Inject
ExampleFragment exampleFragment;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.root, exampleFragment);
}
}
模块保留,但现在注入片段:
@Module
public abstract class MainActivityModule {
@FragmentScoped
@ContributesAndroidInjector(modules = ExampleFragmentModule.class)
abstract ExampleFragment exampleFragment();
}
现在编译失败并出现错误:
Error:(13, 8) error: [dagger.android.AndroidInjector.inject(T)] com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragmentContract.Presenter cannot be provided without an @Provides-annotated method.
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragmentContract.Presenter is injected at
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragment.mPresenter
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragment is injected at
com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivity.exampleFragment
com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivityModule_ExampleFragment.ExampleFragmentSubcomponent
在我看来,我有两层深的子组件,而匕首忽略了更深的模块。这是我做不到的吗?
在您的 ExampleFragmentPresenter 中,您缺少范围界定
@FragmentScoped
public class ExampleFragmentPresenter implements ExampleFragmentContract.Presenter
此外,您正在尝试将片段作用域注入添加到来自 MainActivity
的 activity 作用域中
@Inject
ExampleFragment exampleFragment;
这是错误的,因为您的 activity 作用域对您的片段注入一无所知,所以另外还要这样做:
public class MainActivity extends DaggerAppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.root, ExampleFragment.newInstance());
}
}
// removed @Inject here
public ExampleFragment() {
}
我想要一个提供视图(片段)和演示者的片段模块。 View 依赖于 presenter,presenter 依赖于 view,而 dagger 负责处理这些依赖关系。
我见过这种方法适用于活动和演示者,但未能将这种模式应用于片段。我想知道这是由于我的代码错误,还是 dagger 的限制。
这是我用于活动的基准代码:
主要Activity合同
public interface MainActivityContract {
interface View {
void setText(String text);
}
interface Presenter {
void attach();
}
}
主要Activity模块
@Module
public abstract class MainActivityModule {
@Binds
abstract MainActivityContract.View exampleFragment(MainActivity view);
@Binds
abstract MainActivityContract.Presenter exampleFragmentPresenter(MainActivityPresenter presenter);
}
Activity代码:
public class MainActivity extends DaggerAppCompatActivity implements MainActivityContract.View {
@Inject
MainActivityContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPresenter.attach();
}
@Override
public void setText(String text) {
((TextView) findViewById(R.id.example_text)).setText(text);
}
}
演示者代码:
public class MainActivityPresenter implements MainActivityContract.Presenter {
private MainActivityContract.View mView;
@Inject
public MainActivityPresenter(MainActivityContract.View view) {
mView = view;
}
public void attach() {
this.mView.setText("Hello world!");
}
}
普通匕首-android设置:
申请代码
public class MyApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().application(this).build();
}
}
AppComponent
@Component(modules = {ActivityBindingModule.class, AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<MyApplication> {
@Component.Builder
interface Builder {
@BindsInstance
AppComponent.Builder application(Application application);
AppComponent build();
}
}
Activity绑定模块
@Module
public abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity mainActivity();
}
现在我想将 activity 转换成片段。
重复上述模式,唯一不同的是片段代码:
public class ExampleFragment extends DaggerFragment implements ExampleFragmentContract.View {
@Inject
ExampleFragmentContract.Presenter mPresenter;
@Inject
public ExampleFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.example_fragment, container, false);
}
@Override
public void setText(String text) {
((TextView) getView().findViewById(R.id.example_text)).setText(text);
}
}
Main Activity 变笨了,演示者被删除了:
public class MainActivity extends DaggerAppCompatActivity {
@Inject
ExampleFragment exampleFragment;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.root, exampleFragment);
}
}
模块保留,但现在注入片段:
@Module
public abstract class MainActivityModule {
@FragmentScoped
@ContributesAndroidInjector(modules = ExampleFragmentModule.class)
abstract ExampleFragment exampleFragment();
}
现在编译失败并出现错误:
Error:(13, 8) error: [dagger.android.AndroidInjector.inject(T)] com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragmentContract.Presenter cannot be provided without an @Provides-annotated method.
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragmentContract.Presenter is injected at
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragment.mPresenter
com.example.michael.daggerfragmentexample.ui.ExampleFragment.ExampleFragment is injected at
com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivity.exampleFragment
com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.example.michael.daggerfragmentexample.ui.MainActivity.MainActivityModule_ExampleFragment.ExampleFragmentSubcomponent
在我看来,我有两层深的子组件,而匕首忽略了更深的模块。这是我做不到的吗?
在您的 ExampleFragmentPresenter 中,您缺少范围界定
@FragmentScoped
public class ExampleFragmentPresenter implements ExampleFragmentContract.Presenter
此外,您正在尝试将片段作用域注入添加到来自 MainActivity
的 activity 作用域中@Inject
ExampleFragment exampleFragment;
这是错误的,因为您的 activity 作用域对您的片段注入一无所知,所以另外还要这样做:
public class MainActivity extends DaggerAppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.root, ExampleFragment.newInstance());
}
}
// removed @Inject here
public ExampleFragment() {
}