Reputation: 113
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 ?
Upvotes: 4
Views: 9010
Reputation: 13321
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.
Upvotes: 5