如何在android库项目中使用dagger

时间:2021-10-22 22:49:16

I'm currently trying to add Dagger to my android projects. For the apps projects its easy and clear to me, how to build the ObjectGraph. But I dont quite know whats the best way to do this in my android library projects.

我正在尝试将Dagger添加到我的android项目中。对于应用程序项目,我很容易清楚,如何构建ObjectGraph。但我不知道在我的android库项目中最好的方法是什么。

Should I keep building the ObjectGraph in the Application class of the apps and pass the OG over to a LibraryModule - plussing the OG of library to the Apps OG? Or should i build the whole ObjectGraph in the library?

我应该继续在应用程序的Application类中构建ObjectGraph并将OG传递给LibraryModule - 将库的OG插入到Apps OG中吗?或者我应该在库中构建整个ObjectGraph?

What if I need to inject a class in the library by ObjectGraph.inject(this)? In my Apps projects I can get the OG from the Application class. But how to handle this in the library? Should I add a @Provides method for the ObjectGraph?

如果我需要通过ObjectGraph.inject(this)在库中注入一个类怎么办?在我的Apps项目中,我可以从Application类中获取OG。但如何在图书馆处理这个?我应该为ObjectGraph添加@Provides方法吗?

Big thanks for your help.

非常感谢你的帮助。

Edit: In short: How can I call ObjectGraph.inject(this) in my library project where I don't have access to the OG because it is being builded in the Application Class?

编辑:简而言之:如何在我无法访问OG的库项目中调用ObjectGraph.inject(this),因为它正在Application类中构建?

4 个解决方案

#1


22  

In case someone using Dagger 2 gets here, this is the way I've done in my App:

如果有人使用Dagger 2来到这里,这就是我在我的应用程序中所做的方式:

In the library module I've created the following Module and Component:

在库模块中,我创建了以下模块和组件:

@Module
public class ModuleUtil {

    @Provides
    public RestTemplate provideRestTemplate() {
        return new RestTemplate();
    }

}

@Singleton
@Component(
        modules = {
                ModuleUtil.class
        })
public interface MainComponent {
    void inject(Postman postman);
}

And then I've created the Singleton below in order to manage the injections:

然后我在下面创建了Singleton以管理注射:

public class DaggerWrapper {

    private static MainComponent mComponent;

    public static MainComponent getComponent() {
        if (mComponent == null) {
            initComponent();
        }
        return mComponent;
    }

    private static void initComponent () {
       mComponent = DaggerMainComponent
                .builder()
                .utilModule(new ModuleUtil())
                .build();
    }
}

When some class from the library module needs to inject its members, I simply call DaggerWrapper.getComponent().inject(this); and that't it.

当库模块中的某些类需要注入其成员时,我只需调用DaggerWrapper.getComponent()。inject(this);那就是它。

#2


10  

I'm doing this way:

我是这样做的:

  1. @Module classes belong to the main project and they provide implementations which you are injecting to library elements, so there are no @Module classes in the library projects

    @Module类属于主项目,它们提供了向库元素注入的实现,因此库项目中没有@Module类

  2. Library elements which are expecting dependency must have access to ObjectGraph and call .inject() on themselves, but main project should give ObjectGraph instance to the library with provided @Module dependency

    期望依赖的库元素必须能够访问ObjectGraph并自己调用.inject(),但主项目应该使用提供的@Module依赖项将ObjectGraph实例提供给库

  3. How to get ObjectGraph from main project into the library? You could have interface like this:

    如何将ObjectGraph从主项目导入库中?你可以有这样的界面:

    interface Injector {
        void inject(Object object);
        public ObjectGraph getObjectGraph(); 
    }

Context objects like Activity or Application class implements this interface (holders of ObjectGraph objects).

像Activity或Application类这样的Context对象实现了这个接口(ObjectGraph对象的持有者)。

If you have example of Activity in the library module which needs something to inject from the main project this would look like this:

如果你在库模块中有Activity的例子,它需要从主项目中注入一些东西,它将如下所示:

class LibraryActivity extends Activity {

    @Inject ActivationModule instance;

    void onCreate(... ) {
        Injector injector = (Injector)getApplicationContext();
        injector.inject(this)
    }
}

ActivationModule is the class/interface in the library project.

ActivationModule是库项目中的类/接口。

Main project has application class which implements Injector interface and creates ObjectGraph with provided dependecy for ActivationModule in the library project.

主项目具有应用程序类,该类实现Injector接口并创建ObjectGraph,并为库项目中的ActivationModule提供依赖性。

class MyApplicationInTheMainProject extends Application implements Injector {

    ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();
        graph = ObjectGraph.create(new ActivationModuleImpl(this));
    }

    @Override public void inject(Object object) {
        graph.inject(object);
    }

    @Override public ObjectGraph getObjectGraph() {
        return graph;
    }
}


@Module(injects = {
        LibraryActivity.class
}, library = true)
class ActivationModuleImpl implements ActivationModule {
    ....
}

#3


3  

if you are giving this library to people and they dont know nothing about your scenario so you must write it in a way that your Dagger works perfectly without any help from user. (the easier to work with the better practice)

如果您将这个图书馆提供给人们并且他们对您的场景一无所知,那么您必须以您的Dagger完美工作的方式编写它,而无需用户的任何帮助。 (使用更好的练习更容易)

i just wrote some library for you to show how to do it. i wrote the library in a way that you can even run it standalone and see the result in the messages tab. user of your library doesnt need to know nothing about dagger and does nothing he just uses the library and dagger will be configured:

我刚刚给你写了一些图书馆来展示如何做到这一点。我以一种你甚至可以独立运行它的方式编写库,并在消息选项卡中查看结果。你的图书馆的用户不需要对匕首一无所知,也没有做任何他只是使用图书馆和匕首的配置:

https://github.com/amirziaratii/libraryUsingDagger.git

https://github.com/amirziaratii/libraryUsingDagger.git

if this library is something you use it yourself and for your own project, the best practice is do it like in this project of my friend:

如果这个库是您自己使用的,对于您自己的项目,那么最好的做法就是在我朋友的这个项目中这样做:

https://github.com/mmirhoseini/trakt.tv

https://github.com/mmirhoseini/trakt.tv

all your questions are answered in these two projects. ask any question and ill answer in comment.

您在这两个项目中回答了所有问题。在评论中提出任何问题和不良答案。

#4


-3  

Here is the full example how to use dagger with in the application Step 1 Add depedancy to project level gradle classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' Step 2 Module level depedancy

下面是如何在应用程序中使用dagger的完整示例步骤1将depedancy添加到项目级gradle类路径'com.neenbedankt.gradle.plugins:android-apt:1.8'步骤2模块级别depedancy

apply plugin: 'com.android.application' apply plugin: 'android-apt' apply plugin: 'com.neenbedankt.android-apt'

apply plugin:'com.android.application'apply plugin:'android-apt'apply plugin:'com.neenbedankt.android-apt'

compile 'com.google.dagger:dagger:2.0'
provided 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'

Step 3 Build Dagger with your application class

步骤3使用您的应用程序类构建Dagger

public class TubeMateApp extends Application {

公共类TubeMateApp扩展Application {

public  AppComponent component;
public static TubeMateApp singleton;


public static TubeMateApp getInstance() {
    return singleton;
}

@Override
public void onCreate() {
    super.onCreate();
    singleton = this;
    setupGraph();
}

private void setupGraph() {
    component = DaggerAppComponent.builder()
            .appModule(new AppModule(this))
            .build();

    component.inject(this);
}


public AppComponent component() {
    return component;
}

} Step 4 Create AppModule like this

第4步像这样创建AppModule

@Module public class AppModule {

@Module public class AppModule {

private TubeMateApp app;

public AppModule(TubeMateApp application) {
    this.app = application;
}



@Provides
public Application provideApplication() {
    return app;
}

@Provides
@Singleton
Prefs prefs(){
    return Prefs.with(app);
}

// To use your custom requirement code here for example i have used Picasso with in the application

@Provides
@Singleton
Picasso getPicasso(){
    return Picasso.with(app);
}

@Provides
@Singleton
LayoutInflater getLayoutInflater() {
    return (LayoutInflater) app.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

} Step 5 Create Application Components which is need to be inject dagger App Components here Step 6 Use dagger in main splash activity how to apply dagger inject see this screenshot

步骤5创建需要在这里注入匕首App组件的应用程序组件步骤6在主要启动活动中使用匕首如何应用匕首注入请参阅此屏幕截图

#1


22  

In case someone using Dagger 2 gets here, this is the way I've done in my App:

如果有人使用Dagger 2来到这里,这就是我在我的应用程序中所做的方式:

In the library module I've created the following Module and Component:

在库模块中,我创建了以下模块和组件:

@Module
public class ModuleUtil {

    @Provides
    public RestTemplate provideRestTemplate() {
        return new RestTemplate();
    }

}

@Singleton
@Component(
        modules = {
                ModuleUtil.class
        })
public interface MainComponent {
    void inject(Postman postman);
}

And then I've created the Singleton below in order to manage the injections:

然后我在下面创建了Singleton以管理注射:

public class DaggerWrapper {

    private static MainComponent mComponent;

    public static MainComponent getComponent() {
        if (mComponent == null) {
            initComponent();
        }
        return mComponent;
    }

    private static void initComponent () {
       mComponent = DaggerMainComponent
                .builder()
                .utilModule(new ModuleUtil())
                .build();
    }
}

When some class from the library module needs to inject its members, I simply call DaggerWrapper.getComponent().inject(this); and that't it.

当库模块中的某些类需要注入其成员时,我只需调用DaggerWrapper.getComponent()。inject(this);那就是它。

#2


10  

I'm doing this way:

我是这样做的:

  1. @Module classes belong to the main project and they provide implementations which you are injecting to library elements, so there are no @Module classes in the library projects

    @Module类属于主项目,它们提供了向库元素注入的实现,因此库项目中没有@Module类

  2. Library elements which are expecting dependency must have access to ObjectGraph and call .inject() on themselves, but main project should give ObjectGraph instance to the library with provided @Module dependency

    期望依赖的库元素必须能够访问ObjectGraph并自己调用.inject(),但主项目应该使用提供的@Module依赖项将ObjectGraph实例提供给库

  3. How to get ObjectGraph from main project into the library? You could have interface like this:

    如何将ObjectGraph从主项目导入库中?你可以有这样的界面:

    interface Injector {
        void inject(Object object);
        public ObjectGraph getObjectGraph(); 
    }

Context objects like Activity or Application class implements this interface (holders of ObjectGraph objects).

像Activity或Application类这样的Context对象实现了这个接口(ObjectGraph对象的持有者)。

If you have example of Activity in the library module which needs something to inject from the main project this would look like this:

如果你在库模块中有Activity的例子,它需要从主项目中注入一些东西,它将如下所示:

class LibraryActivity extends Activity {

    @Inject ActivationModule instance;

    void onCreate(... ) {
        Injector injector = (Injector)getApplicationContext();
        injector.inject(this)
    }
}

ActivationModule is the class/interface in the library project.

ActivationModule是库项目中的类/接口。

Main project has application class which implements Injector interface and creates ObjectGraph with provided dependecy for ActivationModule in the library project.

主项目具有应用程序类,该类实现Injector接口并创建ObjectGraph,并为库项目中的ActivationModule提供依赖性。

class MyApplicationInTheMainProject extends Application implements Injector {

    ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();
        graph = ObjectGraph.create(new ActivationModuleImpl(this));
    }

    @Override public void inject(Object object) {
        graph.inject(object);
    }

    @Override public ObjectGraph getObjectGraph() {
        return graph;
    }
}


@Module(injects = {
        LibraryActivity.class
}, library = true)
class ActivationModuleImpl implements ActivationModule {
    ....
}

#3


3  

if you are giving this library to people and they dont know nothing about your scenario so you must write it in a way that your Dagger works perfectly without any help from user. (the easier to work with the better practice)

如果您将这个图书馆提供给人们并且他们对您的场景一无所知,那么您必须以您的Dagger完美工作的方式编写它,而无需用户的任何帮助。 (使用更好的练习更容易)

i just wrote some library for you to show how to do it. i wrote the library in a way that you can even run it standalone and see the result in the messages tab. user of your library doesnt need to know nothing about dagger and does nothing he just uses the library and dagger will be configured:

我刚刚给你写了一些图书馆来展示如何做到这一点。我以一种你甚至可以独立运行它的方式编写库,并在消息选项卡中查看结果。你的图书馆的用户不需要对匕首一无所知,也没有做任何他只是使用图书馆和匕首的配置:

https://github.com/amirziaratii/libraryUsingDagger.git

https://github.com/amirziaratii/libraryUsingDagger.git

if this library is something you use it yourself and for your own project, the best practice is do it like in this project of my friend:

如果这个库是您自己使用的,对于您自己的项目,那么最好的做法就是在我朋友的这个项目中这样做:

https://github.com/mmirhoseini/trakt.tv

https://github.com/mmirhoseini/trakt.tv

all your questions are answered in these two projects. ask any question and ill answer in comment.

您在这两个项目中回答了所有问题。在评论中提出任何问题和不良答案。

#4


-3  

Here is the full example how to use dagger with in the application Step 1 Add depedancy to project level gradle classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' Step 2 Module level depedancy

下面是如何在应用程序中使用dagger的完整示例步骤1将depedancy添加到项目级gradle类路径'com.neenbedankt.gradle.plugins:android-apt:1.8'步骤2模块级别depedancy

apply plugin: 'com.android.application' apply plugin: 'android-apt' apply plugin: 'com.neenbedankt.android-apt'

apply plugin:'com.android.application'apply plugin:'android-apt'apply plugin:'com.neenbedankt.android-apt'

compile 'com.google.dagger:dagger:2.0'
provided 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'

Step 3 Build Dagger with your application class

步骤3使用您的应用程序类构建Dagger

public class TubeMateApp extends Application {

公共类TubeMateApp扩展Application {

public  AppComponent component;
public static TubeMateApp singleton;


public static TubeMateApp getInstance() {
    return singleton;
}

@Override
public void onCreate() {
    super.onCreate();
    singleton = this;
    setupGraph();
}

private void setupGraph() {
    component = DaggerAppComponent.builder()
            .appModule(new AppModule(this))
            .build();

    component.inject(this);
}


public AppComponent component() {
    return component;
}

} Step 4 Create AppModule like this

第4步像这样创建AppModule

@Module public class AppModule {

@Module public class AppModule {

private TubeMateApp app;

public AppModule(TubeMateApp application) {
    this.app = application;
}



@Provides
public Application provideApplication() {
    return app;
}

@Provides
@Singleton
Prefs prefs(){
    return Prefs.with(app);
}

// To use your custom requirement code here for example i have used Picasso with in the application

@Provides
@Singleton
Picasso getPicasso(){
    return Picasso.with(app);
}

@Provides
@Singleton
LayoutInflater getLayoutInflater() {
    return (LayoutInflater) app.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

} Step 5 Create Application Components which is need to be inject dagger App Components here Step 6 Use dagger in main splash activity how to apply dagger inject see this screenshot

步骤5创建需要在这里注入匕首App组件的应用程序组件步骤6在主要启动活动中使用匕首如何应用匕首注入请参阅此屏幕截图