Java Dagger2无法生成组件类
我正在使用Dagger2构建一个应用程序。在我尝试将RecylerAdapter和LayoutManager转换为注入对象之前,我使用Dagger2进行依赖项注入。当我尝试添加这些时,会出现各种各样的错误。为了更好地理解Dagger2,我读了越来越多的书,我修正了一些东西,但仍然不确定为什么它不起作用。我得到了很多编译错误,我认为这与我的依赖性有关,但我现在不知所措。我得到的错误是:Java Dagger2无法生成组件类,java,android,dependency-injection,dagger-2,dagger,Java,Android,Dependency Injection,Dagger 2,Dagger,我正在使用Dagger2构建一个应用程序。在我尝试将RecylerAdapter和LayoutManager转换为注入对象之前,我使用Dagger2进行依赖项注入。当我尝试添加这些时,会出现各种各样的错误。为了更好地理解Dagger2,我读了越来越多的书,我修正了一些东西,但仍然不确定为什么它不起作用。我得到了很多编译错误,我认为这与我的依赖性有关,但我现在不知所措。我得到的错误是: D:\Development\Android\Projects\GiantBombForAndroid\app\
D:\Development\Android\Projects\GiantBombForAndroid\app\src\main\java\com\app\int_a\giantbombforandroid\main\App.java
Error:(5, 61) error: cannot find symbol class DaggerNetComponent
D:\Development\Android\Projects\GiantBombForAndroid\app\src\main\java\com\app\int_a\giantbombforandroid\main\mainscreen\MainActivity.java
Error:(11, 61) error: cannot find symbol class DaggerMainScreenComponent
D:\Development\Android\Projects\GiantBombForAndroid\app\src\main\java\com\app\int_a\giantbombforandroid\main\data\component\MainScreenComponent.java
Error:(16, 10) error: java.util.List<com.app.int_a.giantbombforandroid.main.model.Result> cannot be provided without an @Provides-annotated method.
com.app.int_a.giantbombforandroid.main.mainscreen.MainActivity.recyclerAdapter
[injected field of type: com.app.int_a.giantbombforandroid.main.mainscreen.MainScreenRecyclerAdapter recyclerAdapter]
com.app.int_a.giantbombforandroid.main.data.module.MainScreenModule.provideMainScreenRecyclerAdapter(java.util.List<com.app.int_a.giantbombforandroid.main.model.Result> videoList, android.content.Context context)
[parameter: java.util.List<com.app.int_a.giantbombforandroid.main.model.Result> videoList]
D:\Development\Android\Projects\GiantBombForAndroid\app\src\main\java\com\app\int_a\giantbombforandroid\main\data\component\NetComponent.java
Error:(23, 10) error: com.app.int_a.giantbombforandroid.main.mainscreen.MainScreenRecyclerAdapter cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
com.app.int_a.giantbombforandroid.main.mainscreen.MainActivity.recyclerAdapter
[injected field of type: com.app.int_a.giantbombforandroid.main.mainscreen.MainScreenRecyclerAdapter recyclerAdapter]
NetComponent.java
@CustomScope
@Component(dependencies = NetComponent.class, modules = MainScreenModule.class)
public interface MainScreenComponent {
void inject(MainActivity activity);
}
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
// downstream components need these exposed with the return type
// method name does not really matter
Retrofit retrofit();
void inject(MainActivity activity);
}
AppModule.java
@Module
public class AppModule {
Application application;
public AppModule(Application application){
this.application = application;
}
@Provides
@Singleton
Application provideApplication(){
return application;
}
}
@Module
public class MainScreenModule {
private final MainScreenContract.View view;
private final Context context;
private final List<Result> videoList;
private final int numColumns;
public MainScreenModule(MainScreenContract.View view, Context context, List<Result> videoList, int numColumns){
this.view = view;
this.context = context;
this.numColumns = numColumns;
this.videoList = videoList;
}
@Provides
@CustomScope
MainScreenContract.View providesMainScreenContractView(){
return view;
}
@Provides
@CustomScope
MainScreenRecyclerAdapter provideMainScreenRecyclerAdapter(List<Result> videoList, Context context){
return new MainScreenRecyclerAdapter(videoList, context);
}
@Provides
@CustomScope
GridLayoutManager provideGridLayoutManager(Context context, int columns){
return new GridLayoutManager(context, columns);
}
}
@Module
public class NetModule {
// Maybe one day this will be a view object to contain a video?
// Maybe it will become a dependency and will be injected via
// another module? Let Dagger find a view object and create it
public NetModule(){
}
@Provides
@Singleton
SharedPreferences providesSharedPreferences(Application application){
return PreferenceManager.getDefaultSharedPreferences(application);
}
@Provides
@Singleton
Cache provideHttpCache(Application application){
int cacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
@Provides
@Singleton
Gson provideGson(){
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
@Provides
@Singleton
OkHttpClient provideOkhttpClient (Cache cache){
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
// Adds GiantBomb.com api key to request
// Adds json parameter because all requests will expect json
client.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("api_key", BuildConfig.GIANTBOMB_API_KEY)
.addQueryParameter("format","json")
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.url(url);
Timber.d("URL:" + url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
return client.build();
}
@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient){
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.build();
return retrofit;
}
}
MainScreenModule.java
@Module
public class AppModule {
Application application;
public AppModule(Application application){
this.application = application;
}
@Provides
@Singleton
Application provideApplication(){
return application;
}
}
@Module
public class MainScreenModule {
private final MainScreenContract.View view;
private final Context context;
private final List<Result> videoList;
private final int numColumns;
public MainScreenModule(MainScreenContract.View view, Context context, List<Result> videoList, int numColumns){
this.view = view;
this.context = context;
this.numColumns = numColumns;
this.videoList = videoList;
}
@Provides
@CustomScope
MainScreenContract.View providesMainScreenContractView(){
return view;
}
@Provides
@CustomScope
MainScreenRecyclerAdapter provideMainScreenRecyclerAdapter(List<Result> videoList, Context context){
return new MainScreenRecyclerAdapter(videoList, context);
}
@Provides
@CustomScope
GridLayoutManager provideGridLayoutManager(Context context, int columns){
return new GridLayoutManager(context, columns);
}
}
@Module
public class NetModule {
// Maybe one day this will be a view object to contain a video?
// Maybe it will become a dependency and will be injected via
// another module? Let Dagger find a view object and create it
public NetModule(){
}
@Provides
@Singleton
SharedPreferences providesSharedPreferences(Application application){
return PreferenceManager.getDefaultSharedPreferences(application);
}
@Provides
@Singleton
Cache provideHttpCache(Application application){
int cacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
@Provides
@Singleton
Gson provideGson(){
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
@Provides
@Singleton
OkHttpClient provideOkhttpClient (Cache cache){
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
// Adds GiantBomb.com api key to request
// Adds json parameter because all requests will expect json
client.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("api_key", BuildConfig.GIANTBOMB_API_KEY)
.addQueryParameter("format","json")
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.url(url);
Timber.d("URL:" + url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
return client.build();
}
@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient){
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.build();
return retrofit;
}
}
App.java
public class App extends Application {
private NetComponent netComponent;
@Override
public void onCreate(){
super.onCreate();
netComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule())
.build();
}
public NetComponent getNetComponent(){
return netComponent;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements MainScreenContract.View {
ArrayList<Result> list = new ArrayList<>();
// Objects for RecyclerView
@BindView(R.id.my_recycler_list)
RecyclerView recyclerView;
@Inject
MainScreenRecyclerAdapter recyclerAdapter;
@Inject
MainScreenPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Timber.plant(new Timber.DebugTree() {
// Add the line number to the tag
@Override
protected String createStackElementTag(StackTraceElement element) {
return super.createStackElementTag(element) + ':' + element.getLineNumber();
}
});
//Call the method in MainPresenter to make Network Request
mainPresenter.loadVideo();
DaggerMainScreenComponent.builder()
.netComponent(((App) getApplicationContext()).getNetComponent())
.mainScreenModule(new MainScreenModule(this, this.getApplicationContext(), list, 2))
.build().inject(this);
Timber.d("Array size: " + list.size());
}
@Override
public void showVideos(Video video){
// Loop through the posts, get the title of the post, and add it to our list object
for(int i = 0; i < video.getResults().size(); i++){
Result currentVideo = video.getResults().get(i);
// Filter out Premium videos since these would require authentication
if(currentVideo.getVideoType() != null && !currentVideo.getVideoType().equals("Premium")) {
list.add(currentVideo);
Timber.d("List item " + i + " = " + list.get(list.size()-1));
}
}
// RecyclerView implementation
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recyclerAdapter = new MainScreenRecyclerAdapter(list, this.getApplicationContext());
recyclerView.setAdapter(recyclerAdapter);
// set to true because all images will be the same size
recyclerView.setHasFixedSize(true);
}
@Override
public void showError(String message){
// Show error message text as a Toast message
Toast.makeText(getApplicationContext(), "Error" + message, Toast.LENGTH_SHORT).show();
Timber.e("Error: " + message);
}
@Override
public void showComplete(){
// Show completed Toast message
Toast.makeText(getApplicationContext(), "Complete", Toast.LENGTH_SHORT).show();
}
}
公共类MainActivity扩展AppCompatActivity实现MainScreenContract。查看{
ArrayList=新建ArrayList();
//用于RecyclerView的对象
@BindView(R.id.my_回收者列表)
回收视图回收视图;
@注入
主屏幕回收器适配器回收器适配器;
@注入
主屏幕演示者主演示者;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
木材.植物(新木材.树木){
//将行号添加到标记中
@凌驾
受保护字符串createStackElementTag(StackTraceElement元素){
返回super.createStackElementTag(element)+':'+element.getLineNumber();
}
});
//调用MainPresenter中的方法以发出网络请求
mainPresenter.loadVideo();
DaggerMainScreenComponent.builder()
.netComponent(((应用程序)getApplicationContext()).getNetComponent()
.mainScreenModule(新的mainScreenModule(this,this.getApplicationContext(),list,2))
.build().inject(这个);
d(“数组大小:+list.size());
}
@凌驾
公共视频(视频){
//循环浏览帖子,获取帖子的标题,并将其添加到列表对象中
对于(int i=0;i
MainScreenRecyclerAdapter.java
public class MainScreenRecyclerAdapter extends RecyclerView.Adapter {
private List<Result> myDataset;
private Context myContext;
// TODO: Should I make the list contain Video/Result objects and pull the data from that?
public MainScreenRecyclerAdapter(List<Result> dataset, Context context) {
myDataset = dataset;
myContext = context;
}
// Create new views
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(myContext)
.inflate(R.layout.thumbnail_view, parent, false);
final RecyclerView.ViewHolder viewHolder = new VideoViewHolder(v);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Timber.d("Stub for VideoViewHolder onClick() method");
}
});
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((VideoViewHolder) holder).bind(myDataset, position, myContext);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return myDataset.size();
}
}
public类MainScreenRecyclerAdapter扩展了RecyclerView.Adapter{
私有列表数据集;
私人语境;
//TODO:我应该让列表包含视频/结果对象并从中提取数据吗?
public MainScreenRecyclerAdapter(列表数据集、上下文){
myDataset=数据集;
myContext=上下文;
}
//创建新视图
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(视图组父级,int-viewType){
//创建新视图
视图v=LayoutFlater.from(myContext)
.充气(R.layout.U视图,父视图,假);
最终RecyclerView.ViewHolder ViewHolder=新的VideoViewHolder(v);
viewHolder.itemView.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
Timber.d(“VideoViewHolder的存根onClick()方法”);
}
});
返回视图持有者;
}
//替换视图的内容(由布局管理器调用)
@凌驾
BindViewHolder上的公共无效(RecyclerView.ViewHolder,int位置){
((VideoViewHolder)holder.bind(myDataset、position、myContext);
}
//返回数据集的大小(由布局管理器调用)
@凌驾
public int getItemCount(){
返回myDataset.size();
}
}
VideoViewHolder.java
public class VideoViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.thumbnail)
public ImageView thumbnailView;
@BindView(R.id.video_title_view)
public TextView videoTitle;
public VideoViewHolder(View v) {
super(v);
ButterKnife.bind(this, v);
}
public void bind(List<Result> myDataset, int position, Context myContext){
// - get element from dataset at this position
// - replace the contents of hte view with that element
Result currentVideo = myDataset.get(position);
String imageUrl =currentVideo.getImage().getMediumUrl();
Timber.d("Image URL: " + imageUrl);
Picasso.with(myContext).load(imageUrl).into(thumbnailView);
videoTitle.setText(currentVideo.getName());
}
}
公共类VideoViewHolder扩展了RecyclerView.ViewHolder{
@BindView(R.id.缩略图)
公共图像视图缩略图视图;
@BindView(R.id.video\u title\u view)
公共文本视图视频标题;
公共视频视图持有者(视图v){
超级(五);
黄油刀。绑定(这个,v);
}
公共void绑定(列表myDataset、int位置、上下文myContext){
//-从此位置从数据集获取元素
//-用该元素替换hte视图的内容
结果currentVideo=myDataset.get(位置);
字符串imageUrl=currentVideo.getImage().getMediumUrl();
d.(“图像URL:+imageUrl”);
Picasso.with(myContext).load(imageUrl).into(thumbnailView);
videoTitle.setText(currentVideo.getName());
}
}
我知道这里有很多代码。感谢您的帮助 您的错误:
如果没有@Inject,则无法提供MainScreenRecyclerAdapter
构造函数或@Provides-或@products带注释的方法
因此,您必须为您的MainScreenRecyclerAdapter
添加广告@Inject
。因为您在MainScreenModule
中提供了此适配器。所以你的适配器应该