作者:bjkml | 来源:互联网 | 2023-01-29 08:17
我正在从Dagger 2.11中探索新的dagger.android.我希望不必创建自定义范围注释@PerActivity
.到目前为止,我能够做到以下几点:
1)定义应用程序范围单例并将它们注入活动.
2)定义活动范围非单例依赖关系,并使用它们将它们注入到它们的活动中 @ContributesAndroidInjector
我无法弄清楚的是如何使用它的应用程序范围Singleton和Activity范围非单例.
在下面的示例中,我想要我的活动范围MyActivityDependencyA
并MyActivityDependencyB
可以访问SingletonMyActivityService
以下设置导致:
错误:(24,3)错误:com.example.di.BuildersModule_BindMyActivity.MyActivitySubcomponent(unscoped)可能不引用作用域绑定:@Singleton @Provides com.example.MyActivityService com.example.MyActivitySingletonsModule.provideMyActivityService()
这是我的设置.注意,我定义了单独的MyActivitySingletonsModule
, MyActivityModule
因为我不能在同一个Module文件中混合使用Singleton和非Singleton依赖项.
@Module
public abstract class BuildersModule {
@ContributesAndroidInjector(modules = {MyActivitySingletonsModule.class, MyActivityModule.class})
abstract MyActivity bindMyActivity();
}
}
和
@Module
public abstract class MyActivityModule {
@Provides
MyActivityDependencyA provideMyActivityDependencyA(MyActivityService myActivityService){
return new MyActivityDependencyA(myActivityService);
}
@Provides
MyActivityDependencyB provideMyActivityDependencyB(MyActivityService myActivityService) {
return new MyActivityDependencyB(myActivityService);
}
}
和
@Module
public abstract class MyActivitySingletonsModule {
@Singleton
@Provides
MyActivityService provideMyActivityService() {
return new MyActivityService();
}
}
和
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
AppModule.class,
BuildersModule.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(App application);
AppComponent build();
}
void inject(App app);
}
如果不定义自定义范围注释,甚至可以做我想做的事情吗?
提前致谢!
1> Vandolf Estr..:
为什么要避免自定义范围?Dagger 2.10+中引入的新dagger.android依赖注入框架仍然需要自定义范围.
"我的理解是@ContributesAndroidInjector
不再需要自定义注释,我能够通过使用活动范围中定义的非单例来证明它,而没有任何问题."
@ContributesAndroidInjector
(在v2.11中提供)不会消除对自定义作用域的需要.它仅仅取代了声明@Subcomponent
不使用的类@Subcomponent.Builder
在运行时注入组件所需的依赖项的需要.请查看官方dagger.android用户指南@ContributesAndroidInjector
中的以下代码段;
"专业提示:如果您的子组件及其构建器没有其他方法或超类型,而不是步骤2中提到的方法或超类型,您可以使用@ContributesAndroidInjector为您生成它们.而不是步骤2和3,添加一个抽象模块方法,返回您的活动,使用@ContributesAndroidInjector对其进行注释,并指定要安装到子组件中的模块.如果子组件需要范围,也可以将范围注释应用于该方法."
@ActivityScope
@ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
abstract YourActivity contributeYourActivityInjector();
这里的关键是"如果子组件需要范围,也可以将范围注释应用于方法."
看看下面的代码如何使用的概述@Singleton
,@PerActivity
,@PerFragment
,并@PerChildFragment
与新的定制范围dagger.android注入框架.
// Could also extend DaggerApplication instead of implementing HasActivityInjector
// App.java
public class App extends Application implements HasActivityInjector {
@Inject
AppDependency appDependency;
@Inject
DispatchingAndroidInjector activityInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.create().inject(this);
}
@Override
public AndroidInjector activityInjector() {
return activityInjector;
}
}
// AppModule.java
@Module(includes = AndroidInjectionModule.class)
abstract class AppModule {
@PerActivity
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity mainActivityInjector();
}
// AppComponent.java
@Singleton
@Component(modules = AppModule.class)
interface AppComponent {
void inject(App app);
}
// Could also extend DaggerActivity instead of implementing HasFragmentInjector
// MainActivity.java
public final class MainActivity extends Activity implements HasFragmentInjector {
@Inject
AppDependency appDependency; // same object from App
@Inject
ActivityDependency activityDependency;
@Inject
DispatchingAndroidInjector fragmentInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if (savedInstanceState == null) {
addFragment(R.id.fragment_container, new MainFragment());
}
}
@Override
public final AndroidInjector fragmentInjector() {
return fragmentInjector;
}
}
// MainActivityModule.java
@Module
public abstract class MainActivityModule {
@PerFragment
@ContributesAndroidInjector(modules = MainFragmentModule.class)
abstract MainFragment mainFragmentInjector();
}
// Could also extend DaggerFragment instead of implementing HasFragmentInjector
// MainFragment.java
public final class MainFragment extends Fragment implements HasFragmentInjector {
@Inject
AppDependency appDependency; // same object from App
@Inject
ActivityDependency activityDependency; // same object from MainActivity
@Inject
FragmentDependency fragmentDepency;
@Inject
DispatchingAndroidInjector childFragmentInjector;
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
if (Build.VERSION.SDK_INT = Build.VERSION_CODES.M) {
// Perform injection here for M (API 23) due to deprecation of onAttach(Activity).
AndroidInjection.inject(this);
}
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main_fragment, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
addChildFragment(R.id.child_fragment_container, new MainChildFragment());
}
}
@Override
public final AndroidInjector fragmentInjector() {
return childFragmentInjector;
}
}
// MainFragmentModule.java
@Module
public abstract class MainFragmentModule {
@PerChildFragment
@ContributesAndroidInjector(modules = MainChildFragmentModule.class)
abstract MainChildFragment mainChildFragmentInjector();
}
// MainChildFragment.java
public final class MainChildFragment extends Fragment {
@Inject
AppDependency appDependency; // same object from App
@Inject
ActivityDependency activityDependency; // same object from MainActivity
@Inject
FragmentDependency fragmentDepency; // same object from MainFragment
@Inject
ChildFragmentDependency childFragmentDepency;
@Override
public void onAttach(Context context) {
AndroidInjection.inject(this);
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main_child_fragment, container, false);
}
}
// MainChildFragmentModule.java
@Module
public abstract class MainChildFragmentModule {
}
// PerActivity.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}
// PerFragment.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerFragment {
}
// PerChildFragment.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerChildFragment {
}
// AppDependency.java
@Singleton
public final class AppDependency {
@Inject
AppDependency() {
}
}
// ActivityDependency.java
@PerActivity
public final class ActivityDependency {
@Inject
ActivityDependency() {
}
}
// FragmentDependency.java
@PerFragment
public final class FragmentDependency {
@Inject
FragmentDependency() {
}
}
// ChildFragmentDependency.java
@PerChildFragment
public final class ChildFragmentDependency {
@Inject
ChildFragmentDependency() {
}
}
有关@ContributesAndroidInjector
上面提到的完整的dagger.android 2.11设置指南和自定义范围,请阅读本文.