有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Dagger 2.11:使用@ContributesAndroidInjector时的本地单例

我使用@ContributesAndroidInjector注释(https://google.github.io/dagger/安卓.html)进行了一个有效的匕首设置

        Component Application
       /                     \
Subcomponent DrawerActivity   Subcomponent SubActivity
      |
Subcomponent DrawerFragment

在SubActivity和DrawerActivity中,我使用的是同一个存储库实例,标记为@Singleton

@Singleton
@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        ActivityBuilderModule.class
})
public interface AppComponent {
    @Component.Builder
    interface Builder{
        @BindsInstance Builder application(Application application);

        AppComponent build();
    }
    void inject(App app);
}

@Module
public abstract class ActivityBuilderModule {
    @PerActivity
    @ContributesAndroidInjector(modules = {DrawerActivityModule.class, 
    FragmentBuilderModule.class})
    abstract DrawerActivity bindDrawerActivity();

    @PerActivity
    @ContributesAndroidInjector(modules = {DrawerActivityModule.class})
    abstract SubActivity bindSubActivity();
}

@Module
public abstract class FragmentBuilderModule {
    @PerFragment
    @ContributesAndroidInjector(modules = DrawerFragmentModule.class)
    abstract DrawerFragment provideDrawerFragment();
}


@Singleton
public class Repository{
    private SomeClass mSomeClass;

    @Inject
    public VehicleRepositoryImpl(SomeClass someClass) {
        mSomeClass = someClass;
    }
}


public class App extends Application implements HasActivityInjector{
    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        }
        AppComponent component = DaggerAppComponent.builder().application(this)
                .build();
        component.inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}    

public class DrawerActivity extends AppCompatActivity implements HasSupportFragmentInjector{
    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return fragmentDispatchingAndroidInjector;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
    }
}

public class DrawerFragment extends Fragment {
    @Inject
    ViewModelFactory mViewModelFactory; //repository gets injected into factory

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        AndroidSupportInjection.inject(this);
        super.onCreate(savedInstanceState);
    }
}

public class SubActivity extends AppCompatActivity{
    @Inject
    Repository mRepository;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
    }
}

我现在需要添加一个用户管理。这需要后勤活动。我不希望存储库在LoginActivity中可用。因此,我想为DrawerActivity/Subactivity/DrawerFragment创建一个本地单例作用域“UserScope”

              Component Application
           /                          \
   @UserScope                       @LoginScope 
   Subcomponent DrawerActivity      SubComponent LoginActivity
      |                        \
Subcomponent DrawerFragment   Subcomponent SubActivity

仍然使用新的@ContributesAndroidInjector注释如何实现这一点

我希望它能像这篇博文一样工作:http://frogermcs.github.io/building-userscope-with-dagger2/


共 (2) 个答案

  1. # 1 楼答案

    1. 什么是范围及其基于什么该范围基于某个android对象及其生命周期。例如Application(已经有了注释@Singleton的默认作用域),ActivityBroadcastReceiverFragmentServiceContentProvider(我从DaggerApplication中获取的这个列表)。所以,取决于它将基于什么对象,您将在该对象的生命周期内获得可重用的依赖关系(它将是它的本地单例,例如活动/片段)
    2. 如何使我的存储库强大首先,您应该选择具有生命周期的对象,这将是我们范围的基础。例如,让我们选择包含两个子片段的片段。我想在这两个子片段中使用相同的CommonInteractor实例。 我们应该为父片段创建独立的子组件。我们可以使用@ContributesAndroidInjector来生成@Subcomponent。这个子组件应该被限定范围,这就是为什么我们把@FragmentScope(我们自己创建的注释)放在它上面。两个子片段将属于此子组件,这就是我们为子片段创建独立模块并通过向父片段子组件的modules添加参数将其添加到生成的子组件中的原因

    ^{pr1}$

    我省略了一些细节,比如描述AppComponent和向其中添加AppBindingModule,以及演示如何使用AndroidSupportInjection进行注入。注入(这)是因为它超出了主题。但如果需要澄清,请在评论中自由提问

  2. # 2 楼答案

    我通过在回购协议中这样做解决了我的问题:

    https://github.com/ragdroid/Dahaka

    非常感谢它的贡献者

    更新1:添加了代码示例

    此图给出了代码示例的大致概念

                     Component Application
               /                               \
       @UserScope                          @LoginScope 
       Subcomponent UserComponent          SubComponent LoginActivity
          |                      \
    Subcomponent DrawerActivity   Subcomponent SubActivity
          |
    SubComponent DrawerFragment
    

    代码示例(如果缺少某些内容,请在注释中告知我):

    1。匕首设置

    AppComponent是Dagger图的根:

    @Singleton
    @Component(modules = {
            AndroidSupportInjectionModule.class,
            AppModule.class,
            AppBindingModule.class 
    })
    public interface AppComponent extends AndroidInjector<DaggerApplication> {
        @Component.Builder
        interface Builder{
            @BindsInstance Builder application(Application application);
    
            AppComponent build();
        }
    
        void inject(MyApp app);
    
        UserComponent.Builder userBuilder();
    
        UserManager getUserManager();
    }
    

    绑定其子组件的模块:

    @Module(subcomponents = UserComponent.class)
    public abstract class AppBindingModule {
    
        @ContributesAndroidInjector(modules = LoginModule.class)
        @LoginScope
        abstract LoginActivity loginActivity();
    
    }    
    

    UserComponent保存仅在用户登录时使用的类的实例。UserModule中提供的所有类。类在进一步的子组件(如活动和片段组件)中以“LocalSingleton”的形式提供

    @UserScope
    @Subcomponent(modules = {
            UserBindingModule.class,
            UserModule.class,
            AndroidSupportInjectionModule.class
    })
    public interface UserComponent extends AndroidInjector<DaggerApplication> {
        void inject(UserManager userManager);
    
        @Subcomponent.Builder
        interface Builder{
            UserComponent build();
        }
    }
    

    UserBindingModule定义属于UserComponent的活动子组件

    @Module
    public abstract class UserBindingModule {
        @ContributesAndroidInjector(modules = {DrawerBindingModule.class, AndroidSupportInjectionModule.class})
        abstract DrawerActivity bindDrawerActivity();
    
        @ContributesAndroidInjector
        abstract SubActivity bindSubActivity();
    }
    

    DroperBinding模块定义哪些片段子组件属于DroperActivityComponent

    @Module
    public abstract class DrawerBindingModule {
        @DrawerFragmentScope
        @ContributesAndroidInjector(modules = DrawerFragmentModule.class)
        abstract DrawerFragment provideDrawerFragment();
    }
    

    UserManager处理用户登录/注销和所有进一步的活动注入

    @Singleton
    public class UserManager implements HasActivityInjector {
        private final UserComponent.Builder userComponentBuilder;
        @Inject
        DispatchingAndroidInjector<Activity> activityInjector;
    
        private UserComponent userComponent;
    
        @Inject
        public UserManager(UserComponent.Builder builder) {
            this.userComponentBuilder = builder;
        }
    
        public void logIn(){
            createUserSession();
        }
    
        private void createUserSession() {
            userComponent = userComponentBuilder.build();
            userComponent.inject(this);
        }
    
        public boolean isLoggedIn() {
            return userComponent != null;
        }
    
        public void logOut() {
            userComponent = null;
        }
    
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return activityInjector;
        }
    }
    

    2。应用程序+活动+片段类

    public class MyApp extends Application implements HasActivityInjector{
        @Inject
        DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
    
        @Inject
        UserManager mUserManager;
    
        @Override
        public void onCreate() {
            super.onCreate();
            if (BuildConfig.DEBUG) {
                Timber.plant(new Timber.DebugTree());
            }
            AppComponent component = DaggerAppComponent.builder().application(this)
                    .build();
            component.inject(this);
        }
    
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return mUserManager.activityInjector();
        }
    }
    
    
    public class LoginActivity extends AppCompatActivity {
        Intent mOpenDrawerActivity;
        private ActivityLoginBinding binding;
    
        @Inject
        UserManager mUserManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            AndroidInjection.inject(this);
            super.onCreate(savedInstanceState);
            ...
        }
    
        void openDrawerActivity(){
            mUserManager.logIn();
            mOpenDrawerActivity = new Intent(this, DrawerActivity.class);
            startActivity(mOpenDrawerActivity);
            finish();
        }
    }
    
    
    public class DrawerActivity extends BaseUserActivity implements HasSupportFragmentInjector{
        @Override
        protected void onCreate(Bundle savedInstanceState) {         
            super.onCreate(savedInstanceState);
            ...
        }        
    
        private void onLogout(){
            logoutUser();
        }  
    }
    
    
    public abstract class BaseUserActivity extends BaseActivity {
        @Inject
        UserManager userManager;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (!userManager.isLoggedIn()) {
                finishView();
            }
        }
    
        @Override
        protected void androidInject() {
            AndroidInjection.inject(this);
        }
    
        protected void logoutUser() {
            userManager.logOut();
            finishView();
        }    
    }
    
    
    public abstract class BaseActivity extends AppCompatActivity implements HasSupportFragmentInjector {
        @Inject
        DispatchingAndroidInjector<Fragment> injector;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            androidInject();
            super.onCreate(savedInstanceState);
        }
    
        protected void androidInject() {
            AndroidInjection.inject(this);
        }
    
        public void finishView() {
            startActivity(new Intent(this, LoginActivity.class));
            finish();
        }
    
        @Override
        public AndroidInjector<Fragment> supportFragmentInjector() {
            return injector;
        }
    }