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上一篇: 访问反应呈现方法中的对象属性
下一篇: 如何避免为每个视图添加注入方法?