I try to create sample application with dagger 2 using mvp & RXAndroid, every thing work correctly but I cannot able to inject Activity the following is my AppComponent
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(App app);
void inject(MainActivity activity);
void inject(ResponseService service);
void inject(MainPresenter presenter);
}
and the following is my Module
@Module
public class AppModule {
private App app;
public AppModule(App app) {
this.app = app;
}
private static final String API_ENDPOINT = "url here";
@Provides
@Singleton
public ApiService apiService() {
OkHttpClient client = new OkHttpClient();
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ClassTypeAdapterFactory())
.registerTypeAdapter(Class.class, new ClassTypeAdapter()).create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
return retrofit.create(ApiService.class);
}
@Provides
@Singleton
ResponseService responseService() {
return new ResponseService(app.getComponent());
}
@Provides
@Singleton
MainPresenter mainPresenter() {
return new MainPresenter(app.getComponent());
}
@Provides
@Singleton
EventBus eventBus() {
return EventBus.getDefault();
}
}
I inject all things correctly and can work with them except ManiActivity when try to use it give me null pointer the following how i inject it
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((App) getApplicationContext())
.getComponent()
.inject(this);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initRecyclerView();
presenter.setView(this);
}
but when try to use it as Context in My adapter and pass it to Picasso library give me the following exception java.lang.IllegalArgumentException: Context must not be null.
the following is how i use it
@Inject
MainActivity activity;
and use it in onBindViewHolder as following
Picasso.with(activity).load(response).fit().into(holder.ivCover);
My adapter code
public class ReAdapter extends RecyclerView.Adapter<ReAdapter.RViewHolder> {
private List<Response> responseList;
@Inject
MainActivity appContext;
public ReAdapter() {
}
public void setResponseList(List<Response> responseList) {
this.responseList = responseList;
notifyDataSetChanged();
}
@Override
public RViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.response_item, parent, false);
return new RViewHolder(view);
}
@Override
public void onBindViewHolder(RViewHolder holder, int position) {
final Response response = responseList.get(position);
Picasso.with(appContext).load(response.getValue().toLowerCase()).fit().into(holder.ivd);
}
@Override
public int getItemCount() {
return responseList != null ? responseList.size() : 0;
}
public class RViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.ivd)
ImageView ivd;
public RViewHolder(View view) {
super(view);
ButterKnife.bind(this, itemView);
}
}
}
Can anyone help me to solve this issue ?
MainActivity doesn't have an @Inject annotated constructor (and can't have, because it's created by the system). AppModule there is no @Provides annotated method that returns MainActivity.The result is Dagger has no idea how to create an object of type MainActivity.
The solution for this specific problem is to use the application context for Picasso or even better create a Picasso object with Dagger.
Update your AppModule with:
@Provides
@Singleton
Picasso providePicasso(App app) {
return Picasso.with(app);
}
In MainActivity add a field:
@Inject
ReAdapter adapter;
In ReAdapter modify the constructor and add a field for picasso:
private final Picasso picasso;
@Inject
public ReAdapter(Picasso picasso) {
this.picasso = picasso;
}
This way Dagger can create a singleton Picasso instance. The ReAdapter is annotated with @Inject (using constructor injection) so Dagger knows how to create it. By adding a ReAdapter field in MainActivity when you call component.inject(this) in MainActivity the adapter field will be initialized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With