How to use dagger in a android library project

2019-01-16 16:32发布

问题:

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.

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?

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?

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?

回答1:

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

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:

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.



回答2:

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

  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

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

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

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

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

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.

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

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:

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)

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

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

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



回答4:

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

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

public class TubeMateApp extends 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

@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