【问题标题】:Can't provide Activity Context with Dagger 2无法使用 Dagger 2 提供活动上下文
【发布时间】:2019-10-14 11:11:41
【问题描述】:

已解决

我是 Dagger 2 的新手,我正在尝试为类提供 Activity 上下文,但没有成功。我搜索了很多,但没有找到任何合适的答案。

我可以提供应用程序上下文。但我也需要提供活动上下文,我不知道有什么好的方法来实现它。

我需要澄清一下,我正在使用 Dagger 作为 Android 依赖项。

def dagger_version = "2.24"
implementation "com.google.dagger:dagger:$dagger_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"

我也只有一个带有以下代码的 AppComponent:

@Singleton
@Component(
        modules = {
                AndroidSupportInjectionModule.class,
                ActivityBuildersModule.class,
                AppModule.class,
                ViewModelFactoryModule.class,
        }
)
public interface AppComponent extends AndroidInjector<BaseApplication> {

    SessionManager sessionManager();

    @Component.Builder
    interface Builder{

        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }
}

除了我的每个活动都有一个模块,但我没有找到为 AppComponent 或从 ActivityModule 注入活动上下文的方法。

这样做的正确方法是什么?

更新

我终于找到了正确的方法。

首先我为要提供的类创建了一个模块

@Module
public class AlertsModule {

    @Provides
    static Alerts provideAlerts(Activity activity){
        return new Alerts(activity);
    }

}

然后我转到要注入该自定义类的 ActivityModules 并执行类似的绑定

@Module
public abstract class MainActivityModule {

    ...

    @Binds
    abstract Activity providesActivity(MainActivity activity);

    ...

}

最后,我将 CustomClassModule 包含在我的 ActivityBuildersModule 中,我使用 @ContributesAndroidInjector 来提供我的活动。

    @MainScope
    @ContributesAndroidInjector(
            modules = {
                    AlertsModule.class,
            }
    )
    abstract MainActivity contributeMainActivity();

【问题讨论】:

  • 我刚开始学习匕首。我需要你帮忙。你找到你问题的答案了吗??如果是,请分享答案。

标签: java android dagger


【解决方案1】:

您可以像当前绑定Application 的实例一样绑定Activity 的实例,方法是使用@Component.Builder 或@Component.Factory。

示例实现如下所示:

@Subcomponent(...)
interface ActivitySubcomponent {

    @Subcomponent.Factory
    interface Factory {
        ActivitySubcomponent create(@BindsInstance MyActivity activity)
    }
}
@Module(subcomponents = [ActivitySubcomponent.class])
class ApplicationModule {
    ....
}
public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        ((MyApplication) getApplication())
            .applicationComponent
            .activitySubcomponentFactory()
            .create(this)
            .inject(this)
    }
}

【讨论】:

  • 我无法让它工作。正如你所说,我创建了一个 ActivitySubcomponent 。我将它作为子组件包含在我的 AppModule 类中。到目前为止还可以。现在我想通过 AppModule 中的构造函数传递 Activity 上下文。前任。 static MyClass provideMyClass(Context context) 我在执行时遇到错误
  • 您不能将Activity 传递给在您的AppModule 中需要它的类。如果该类需要 Activity 作为依赖项,您很可能应该从您的 ActivityModule 中提供该类,并将您的类范围限定为 Activity 的生命周期,否则您可能会遇到内存泄漏。
【解决方案2】:
@Module
class MainActivityModule(mActivity: MainActivity) {

    var mActivity: MainActivity


    init {
        this.mActivity= mActivity
    }


    @Singleton
    @Provides
    fun getMainActivity(): MainActivity{
        return mActivity
    }


}

现在将此模块添加到您的 Component 类中,并将您的活动传递给模块构造函数,同时使用您的组件构建器希望这可以帮助您。

【讨论】:

    【解决方案3】:

    @Named 注释帮助我们区分上下文。我们可以通过添加@Named注解来区分ActivityModule和ContextModule中的context()方法:

    @Module
    public class ActivityModule {
        private final Context context;
    
        ActivityModule(Activity context){
            this.context = context;
        }
    
        @Named("activity_context")
        @Provides
        public Context context(){ return context; }
    }
    
    @Module
    public class ContextModule {
        private final Context context;
    
        ActivityModule(Activity context){
            this.context = context;
        }
    
        @Named("application_context")
        @Provides
        public Context context(){ return context.getApplicationContext(); }
    

    然后,我们告诉 Dagger 使用各自的 Context,如下:

    @Module(includes = ContextModule.class)
    public class OkHttpClientModule {
        ....
        @Provides
        public File file(@Named("application_context") Context context){
        File file = new File(context.getCacheDir(), "HttpCache");
        file.mkdirs();
        return file;
        }
        ....
    }
    

    希望这会有所帮助。

    【讨论】:

    • 我尝试了您的方法,但出现错误:@Component.Builder 缺少所需模块或组件的设置器。我应该在我的 AppComponent 中添加一些东西吗?我的活动没有组件。
    • 试试这个链接link。它与您遇到的错误相同。
    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多