使用 Dagger 注入 RecyclerView.Adapter
Injecting RecyclerView.Adapter using Dagger
我正在尝试将 RecyclerView
适配器注入 Activity
,但我没有得到预期的结果。该列表未被填充。
This is my adapter implementation:
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListItemViewHolder> {
private TopMoviesActivityMVP.Presenter presenter;
public ListAdapter(TopMoviesActivityMVP.Presenter presenter) {
this.presenter = presenter;
}
@NonNull
@Override
public ListAdapter.ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_movie_list, parent, false);
return new ListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ListAdapter.ListItemViewHolder holder, int position) {
presenter.bindRowViewAtPosition(holder, position);
}
@Override
public int getItemCount() {
return presenter.getRowsCount();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder implements TopMoviesRowView {
@BindView(R.id.tv_task_name)
TextView tvName;
@BindView(R.id.tv_task_country)
TextView tvCountry;
public ListItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void setName(String name) {
tvName.setText(name);
}
@Override
public void setCountry(String country) {
tvCountry.setText(country);
}
}}
如您所见,适配器收到 presenter
的一个实例,该实例用于访问下载的数据。在我的 activity
中,我正在尝试注入 adapter
:
public class TopMoviesActivity extends AppCompatActivity implements TopMoviesActivityMVP.View {
@BindView(R.id.list_activity_rootview)
ViewGroup rootView;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Inject
TopMoviesActivityMVP.Presenter presenter;
@Inject
RecyclerView.Adapter<ListAdapter.ListItemViewHolder> listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top_movies);
((App)getApplication()).getComponent().inject(this);
ButterKnife.bind(this);
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
recyclerView.setAdapter(listAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
@Override
protected void onResume() {
super.onResume();
presenter.setView(this);
presenter.loadData();
}
@Override
protected void onDestroy() {
super.onDestroy();
presenter.rxUnsubscribe();
}
@Override
public void updateData() {
int count = presenter.getRowsCount();
if (count == 0) {
listAdapter.notifyItemInserted(0);
} else {
listAdapter.notifyItemInserted(count-1);
}
}
@Override
public void showSnackbar(String msg) {
Snackbar.make(rootView, msg, Snackbar.LENGTH_SHORT).show();
}}
即使在下载数据可用后调用 listAdapter.notifyItemInserted
,也不会调用 onCreateViewHolder
。
如果我不注入适配器,一切都会按预期工作:
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
listAdapter = new ListAdapter(presenter);
recyclerView.setAdapter(listAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
This is my module:
@Module
public class TopMoviesModule {
@Provides
public RecyclerView.Adapter<ListAdapter.ListItemViewHolder> providesAdapter(TopMoviesActivityMVP.Presenter presenter) {
return new ListAdapter(presenter);
}
@Provides
public TopMoviesActivityMVP.Presenter providesTopMoviesPresenter(TopMoviesActivityMVP.Model model) {
return new TopMoviesPresenter(model);
}
@Provides
public TopMoviesActivityMVP.Model providesTopMoviesModel(Repository repository) {
return new TopMoviesModel(repository);
}
@Provides
@Singleton
public Repository providesRepository(MoviesApiService moviesApiService, CountryApiService countryApiService) {
return new TopMoviesRepository(moviesApiService, countryApiService);
}}
我不知道我错过了什么。
我认为这是因为范围界定,问题是因为演示者没有附加范围,所以您在 Activity 和适配器中获得了演示者的 2 个不同实例。您可以通过在代码中添加 break-point 来确认这一点。
此外,拥有一个与应用程序范围绑定的单例范围演示器也是非常错误的。
我建议为您的 Activity 使用自定义范围的子组件,这样它的寿命不会超过 activity,并且您可以将适配器和演示者的范围限定为 Activity .
有关 Dagger 子组件的更多信息,请查看此 link
我正在尝试将 RecyclerView
适配器注入 Activity
,但我没有得到预期的结果。该列表未被填充。
This is my adapter implementation:
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListItemViewHolder> {
private TopMoviesActivityMVP.Presenter presenter;
public ListAdapter(TopMoviesActivityMVP.Presenter presenter) {
this.presenter = presenter;
}
@NonNull
@Override
public ListAdapter.ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_movie_list, parent, false);
return new ListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ListAdapter.ListItemViewHolder holder, int position) {
presenter.bindRowViewAtPosition(holder, position);
}
@Override
public int getItemCount() {
return presenter.getRowsCount();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder implements TopMoviesRowView {
@BindView(R.id.tv_task_name)
TextView tvName;
@BindView(R.id.tv_task_country)
TextView tvCountry;
public ListItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void setName(String name) {
tvName.setText(name);
}
@Override
public void setCountry(String country) {
tvCountry.setText(country);
}
}}
如您所见,适配器收到 presenter
的一个实例,该实例用于访问下载的数据。在我的 activity
中,我正在尝试注入 adapter
:
public class TopMoviesActivity extends AppCompatActivity implements TopMoviesActivityMVP.View {
@BindView(R.id.list_activity_rootview)
ViewGroup rootView;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Inject
TopMoviesActivityMVP.Presenter presenter;
@Inject
RecyclerView.Adapter<ListAdapter.ListItemViewHolder> listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top_movies);
((App)getApplication()).getComponent().inject(this);
ButterKnife.bind(this);
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
recyclerView.setAdapter(listAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
@Override
protected void onResume() {
super.onResume();
presenter.setView(this);
presenter.loadData();
}
@Override
protected void onDestroy() {
super.onDestroy();
presenter.rxUnsubscribe();
}
@Override
public void updateData() {
int count = presenter.getRowsCount();
if (count == 0) {
listAdapter.notifyItemInserted(0);
} else {
listAdapter.notifyItemInserted(count-1);
}
}
@Override
public void showSnackbar(String msg) {
Snackbar.make(rootView, msg, Snackbar.LENGTH_SHORT).show();
}}
即使在下载数据可用后调用 listAdapter.notifyItemInserted
,也不会调用 onCreateViewHolder
。
如果我不注入适配器,一切都会按预期工作:
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
listAdapter = new ListAdapter(presenter);
recyclerView.setAdapter(listAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
This is my module:
@Module
public class TopMoviesModule {
@Provides
public RecyclerView.Adapter<ListAdapter.ListItemViewHolder> providesAdapter(TopMoviesActivityMVP.Presenter presenter) {
return new ListAdapter(presenter);
}
@Provides
public TopMoviesActivityMVP.Presenter providesTopMoviesPresenter(TopMoviesActivityMVP.Model model) {
return new TopMoviesPresenter(model);
}
@Provides
public TopMoviesActivityMVP.Model providesTopMoviesModel(Repository repository) {
return new TopMoviesModel(repository);
}
@Provides
@Singleton
public Repository providesRepository(MoviesApiService moviesApiService, CountryApiService countryApiService) {
return new TopMoviesRepository(moviesApiService, countryApiService);
}}
我不知道我错过了什么。
我认为这是因为范围界定,问题是因为演示者没有附加范围,所以您在 Activity 和适配器中获得了演示者的 2 个不同实例。您可以通过在代码中添加 break-point 来确认这一点。
此外,拥有一个与应用程序范围绑定的单例范围演示器也是非常错误的。
我建议为您的 Activity 使用自定义范围的子组件,这样它的寿命不会超过 activity,并且您可以将适配器和演示者的范围限定为 Activity .
有关 Dagger 子组件的更多信息,请查看此 link