Java 如何在 Android 片段和服务中请求注入?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41303896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:17:10  来源:igfitidea点击:

How do I request injection in Android Fragments and Services?

javaandroidandroid-fragmentsdagger-2

提问by Devesh Agrawal

I'm following this tutorialto add Dagger 2 to my Android project.

我正在按照本教程将 Dagger 2 添加到我的 Android 项目中。

After doing setup and creating the modules and components I can add the dependencies in an Activity like this:

完成设置并创建模块和组件后,我可以在 Activity 中添加依赖项,如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_account);
    ButterKnife.bind(this);
    ((AppController) getApplication()).getNetComponent().inject(this);
}

I am struggling in how to inject dependencies in a Fragment and IntentService?

我正在努力如何在 Fragment 和 IntentService 中注入依赖项?

public class FragmentBrandList extends ListFragment {
}

In this class which @Overridemethod should I request injection in and what will be the code for this?

在这个类中,@Override我应该请求注入哪个方法,它的代码是什么?

回答by Chisko

You can use autodagger2to avoid having to write all that boilerplate. I use this architecture quite often:

您可以使用autodagger2来避免编写所有样板文件。我经常使用这种架构:

build.gradle

构建.gradle

apt 'com.github.lukaspili.autodagger2:autodagger2-compiler:1.1'
compile 'com.github.lukaspili.autodagger2:autodagger2:1.1'

YourApp.java

你的应用程序

@AutoComponent( modules = YourApp.YourAppModule.class )
public class YourApp extends Application {

    private static YourApp instance;
    private YourAppComponent component;

    public YourAppComponent getComponent() {
        return this.component;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        setupComponent();
    }

    private void setupComponent() {
        component = DaggerYourAppComponent.builder()
                .yourAppModule(new YourAppModule(instance))
                .build();
    }


    @dagger.Module
    public static class YourAppModule {
        private YourApp app;

        YourAppModule(YourAppApp application) {
            this.app = application;
        }

        @Provides @AutoExpose(YourApp.class)
        Application provideApplication() {
            return app;
        }

        @Provides @AutoExpose(PoswalaApp.class)
        Context provideContext() {
            return app;
        }

        @Provides @AutoExpose(YourApp.class)
        Retrofit provideApiAdapter() {
            return ApiService.getServiceInstance();
        }
    }
}

YourActivity.java

你的活动.java

@AutoComponent(
    dependencies = YourApp.class,
    modules = YourActivity.YourActivityModule.class
)

public class YourActivity extends BaseActivity implements YourActivityView {

    private YourActivityComponent component;
    @Inject MyPresenter presenter

    // This is an abstract method from BaseActivity
    @Override
    protected void setupComponent(YourAppComponent appComponent) {
        component = DaggerYourActivityComponent.builder()
                .yourAppComponent(((YourApp) getApplication()).getComponent())
                .yourActivityModule(new YourctivityModule(this))
                .build();
    }

    @Override
    protected MyPresenter getPresenter() {
        return presenter;
    }


    @dagger.Module
    public static class YourActivityModule {

        private YourActivityView view;

        YourActivityModule(YourActivityView view) {
            this.view = view;
        }


        @Provides @AutoExpose(YourActivity.class)
        YourActivityView provideView() {
            return view;
        }

        // Your other dependencies
    }
}

Quick explanation:

快速解释:

Your app's module will have to a "universal" dependency, but this way you can achieve using several modules for a class. You just need to customize the

您的应用程序的模块必须具有“通用”依赖项,但通过这种方式,您可以实现为一个类使用多个模块。您只需要自定义

@AutoComponent(
    dependencies = YourApp.class,
    modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)

block. You can add as many modules as you like using that syntax.

堵塞。您可以使用该语法添加任意数量的模块。

Hope this helps you

希望这对你有帮助

回答by EpicPandaForce

You really just need to include the injector method for whatever you want to inject.

你真的只需要为你想要注入的任何东西包含注入器方法。

@Singleton
@Component
public interface AppComponent {
    void inject(MainActivity activity);
    void inject(FragmentBrandList fragmentBrandList);
} 

回答by write2sv

Step 1: Create your ApplicationModule

第 1 步:创建您的 ApplicationModule

@Module
public class ApplicationModule {

    private final DIApplication application;

    public ApplicationModule(DIApplication application) {
        this.application = application;
    }

    @Provides @Singleton
    public DIApplication provideApplication() {
        return application;
    }

    @Provides @Singleton
    public DogModel provideDogModel() {
        return new DogModelImpl("Scooby-doo");
    }

}

Step 2: Create your ApplicationComponent:

第 2 步:创建您的应用程序组件:

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
    void inject(DIApplication application);

    void inject(BaseActivity activity);
    void inject(BaseFragment fragment);

    void inject(DogSyncService service);
}

Step 3: Create a DI Class:

第 3 步:创建一个 DI 类:

public class DependencyInjector {

    private static ApplicationComponent applicationComponent;

    public static void initialize(DIApplication diApplication) {
        applicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(diApplication))
                .build();
    }

    public static ApplicationComponent applicationComponent() {
        return applicationComponent;
    }

    private DependencyInjector(){}
}

Final Step: Inject anywhere using:

最后一步:使用以下方法在任何地方注入:

DependencyInjector.applicationComponent()

Your question inspired me to create a Demo project that shows Activity, Fragment and Service injection using Dagger2. Here is the git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/java/work/shaggy/didemo

您的问题激发了我创建一个演示项目,该项目使用 Dagger2 显示活动、片段和服务注入。这是 git:https: //github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/java/work/shaggy/didemo

回答by David Rawson

In this class which @Override method i should use and what will be the code to add dependency in fragment?

在这个类中,我应该使用哪个@Override 方法以及在片段中添加依赖项的代码是什么?

The correct place to call injection inside a Fragment is onAttach(Context context). This is stated in the where to injectsection of the Dagger 2 user guide here

在 Fragment 中调用注入的正确位置是onAttach(Context context). 这是在说哪里注入匕首2用户指南的部分在这里

@Override
public void onAttach(Context context) {
    ((AppController) context.getApplicationContext()).getNetComponent().inject(this);
    super.onAttach(context);
}

The correct place to call injection inside a Service is onCreate()

在服务中调用注入的正确位置是 onCreate()

@Override 
public void onCreate() {
    ((AppController) getApplication()).getNetComponent().inject(this);
    super.onCreate();

}

Note that in both cases the request for injection comes before the call to super.onCreate(). The Dagger user guide explains it like this:

请注意,在这两种情况下,注入请求都在调用super.onCreate(). Dagger 用户指南是这样解释的:

It is crucial to call AndroidInjection.inject() before super.onCreate() in an Activity, since the call to super attaches Fragments from the previous activity instance during configuration change, which in turn injects the Fragments. In order for the Fragment injection to succeed, the Activity must already be injected. For users of ErrorProne, it is a compiler error to call AndroidInjection.inject() after super.onCreate().

在 Activity 中,在 super.onCreate() 之前调用 AndroidInjection.inject() 至关重要,因为在配置更改期间,对 super 的调用会附加来自先前活动实例的 Fragment,进而注入 Fragments。为了成功注入 Fragment,必须已经注入了 Activity。对于ErrorProne 的用户来说,在super.onCreate() 之后调用AndroidInjection.inject() 是编译器错误。

In other words:

换句话说:

  1. The Activity super.onCreate()call re-attaches Fragments from a previous instance
  2. This supercall in cause Fragments to be re-injected (since Fragments are injected in onAttach)
  3. Fragments should be injected after their Activity is injected, therefore request injection in your Activity before calling super.onCreate().
  1. Activitysuper.onCreate()调用重新附加来自先前实例的 Fragments
  2. 这个super调用导致 Fragments 被重新注入(因为 Fragments 被注入onAttach
  3. Fragments 应该在它们的 Activity 被注入之后被注入,因此在调用super.onCreate().

You can always check where to inject by looking at the relevant source code for the com.google.dagger:dagger-androidclasses like DaggerFragmentand DaggerService. See the GitHub repo here

您始终可以通过查看和 等com.google.dagger:dagger-android类的相关源代码来检查注入的位置。在此处查看GitHub 存储库DaggerFragmentDaggerService

For your specific example, please make sure you have added the new injection sites to the NetComponent:

对于您的具体示例,请确保您已将新注入站点添加到 NetComponent:

void inject(FragmentBrandList frag);

void inject(BrandListService service);

回答by Rumid

I did it using ((AppController) getActivity().getApplication()).getNetComponent().inject(this);

我用 ((AppController) getActivity().getApplication()).getNetComponent().inject(this);

in Fragment.onCreate()method.

Fragment.onCreate()方法。

回答by Adi

((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);

I added this in onAttach(Context context)method of the fragment.

onAttach(Context context)在片段的方法中添加了这个。