How to avoid adding of inject method for each view?

Currently to get instance of for example Picasso in an activity, I need to add inject method to AppComponent. How to avoid adding of the inject method, because I have a lot of fragments and views where it should be injected:

AppComponent.class:

@ForApplication
@Singleton
@Component(
        modules = {AppModule.class,OkHttpClientModule.class,NetworkApiModule.class,NetworkAuthModule.class})
public interface AppComponent {
    void inject(Fragment1 obj);
    void inject(Fragment2 obj);
    void inject(Fragment3 obj);
    void inject(Fragment4 obj);    
    void inject(Fragment5 obj);    
    void inject(Fragment6 obj);
    ...
    }

Fragment1.class

public class Fragment1 extends Fragment {
    @Inject Picasso mPicasso;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyApplication.getComponent(getContext()).inject(this);
    }
}

My classes :

AppModule.class:

@Module
public class AppModule {
    private MyApplication mApplication;

    public AppModule(@NonNull MyApplication mApplication) {
        this.mApplication = mApplication;
    }

    @Provides
    @NonNull
    @Singleton
    public Application provideApplication() {
        return mApplication;
    }


   @Provides
   @ForApplication
    Context provideContext(){
        return mApplication;
    }

    @Provides
    @Singleton
    Picasso providesPicasso(@ForApplication Context context) {
        return new Picasso.Builder(context).build();
    }
}

ForApplication.class:

@Scope
@Retention(RUNTIME)
public @interface ForApplication {
}

MyApplication.class

public class MyApplicationextends Application {
    static Context mContext;
    private AppComponent component;
    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;

        setupComponent();
    }

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

    public AppComponent getComponent() {
        if (component==null)
            setupComponent();
        return component;
    }



public static AppComponent getComponent(Context context) {
        return ((MyApplication) context.getApplicationContext()).getComponent();
    }

UPDATE

I want also inject adapters for fragments, and if I'll add inject to BaseFragment then BaseFragment will have all adapters for all child fragments


One solution would be to use inheritance for the injection.

Just define a BaseFragment with a @Inject Picasso instance, create a injection method in your DaggerComponent for this BaseFragment and call it in the onCreate method of the BaseFragment. The more specific Fragments like Fragment1, 2.. can inherit from this BaseFragment and use the Picasso instance.


The solution is you can do the inheritance ex: use extend Activity or Fragment and do injection in onCreate() in those class

Below is the example what i do:

Graph.java

@Singleton
@Component(modules = {
        AppModule.class,
})

public interface Graph {

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

BaseActivity.java

public class BaseActivity extends AppCompatActivity {
    protected List<Subscription> mSubscriptions;

    @Inject
    protected SharedDB dm;

    @Inject
    protected RestApi restApi;

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

    public Graph getGraph() {
        return MyApplication.graph(this);
    }

    //...
}

BaseFragment.java

public class BaseFragment extends Fragment {

    protected List<Subscription> mSubscriptions;
    protected Unbinder unbinder;

    @Inject
    protected SharedDB dm;

    @Inject
    protected RestApi restApi;

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

    public Graph getGraph() {
        return MyApplication.graph(getActivity());
    }

    //....
}

MyApplication.java

public class MyApplication extends Application {

    private Graph mGraph;

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

        setGraph(DaggerGraph.builder()
                .appModule(new AppModule(this))
                .build());
    }

    public Graph getGraph() {
        return mGraph;
    }

    public void setGraph(Graph graph) {
        mGraph = graph;
    }

    public static Graph graph(Context context) {
        DominoApp app = (DominoApp) context.getApplicationContext();
        return app.getGraph();
    }

    //....
}

What about this?

public final class MySimpleDelegate {

    @Inject
    protected Picasso picasso;

    @Inject
    protected Lazy<AdapterOne> lazyAdapterOne;

    @Inject
    protected Provider<AdapterTwo> providerAdapterTwo;

    public MySimpleDelegate(Context context) {
        MyApplication.getComponent(context).inject(this);
    }

    @NonNull
    public void getPicasso() {
        return picasso;
    }

    @NonNull
    AdapterOne getAdapterOne() {
        // the object is injected when the following method is called
        return lazyAdapterOne.get();
    }

    @NonNull
    AdapterTwo getAdapterTwo() {
        // a new instance is created every time this methos is called
        return providerAdapterTwo.get();
    }
}

public class Fragment1 extends Fragment {

    private MySimpleDelegate delegate;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        delegate = new MySimpleDelegate(getContext());

        Picasso picasso = delegate.getPicasso();
        AdapterOne one = delegate.getAdapterOne();
        AdapterTwo two = delegate.getAdapterTwo();
    }
}

By the way, if the only problem is Picasso, it also provides a 'setSingletonInstance' method. See this link

EDIT

I believe that you can reach what you want using dagger's Provider or Lazy factories. See the example above.

链接地址: http://www.djcxy.com/p/36218.html

上一篇: 访问反应呈现方法中的对象属性

下一篇: 如何避免为每个视图添加注入方法?