【问题标题】:Injecting RecyclerView.Adapter using Dagger使用 Dagger 注入 RecyclerView.Adapter
【发布时间】:2025-12-03 01:45:01
【问题描述】:

我正在尝试将RecyclerView 适配器注入Activity,但我没有得到我期望的结果。该列表未填写。

这是我的适配器实现:

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));
}

这是我的模块:

@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);
}}

我不知道我错过了什么。

【问题讨论】:

    标签: android dependency-injection android-recyclerview dagger-2 android-mvp


    【解决方案1】:

    我认为这是因为范围界定,问题是由于演示者没有附加范围,因此您在 Activity 和适配器中获得了 2 个不同的演示者实例。您可以通过在代码中添加断点来确认。

    另外,如果有一个与 Application 范围绑定在一起的单例范围的 Presenter,那也是非常错误的。

    我建议为您的 Activity 使用具有自定义范围的子组件,这样它就不会超过 Activity,并且您可以将适配器和演示器的范围限定为该 Activity。

    有关 Dagger 子组件的更多信息,请查看link

    【讨论】:

    • 你完全正确。我得到了演示者的两个不同实例。将 @Singleton 注释添加到演示者提供程序可以修复它,但我将阅读 Subcomponents 主题。谢谢