android - 如何将 Activity 和 Fragment 注入(inject) RecyclerAdapter (Dagger 2)

标签 android dependency-injection dagger-2

各位!

我对 Dagger2 很陌生,但我真的很想了解它。因此,首先,让我们看一下 RecyclerAdapter 的代码,我已经通过一些应用程序级注入(inject)(DbHelper 和应用程序上下文)实现了它。

另外,请注意,这里我们有两个 DataSetChangeListener 和 DataProviderListener 实例:

  • DataSetChangeListener - 是调用 Fragment(管理 View )中某些方法的接口(interface);
  • DataProviderListener - 是一个在 Activity 中调用方法的接口(interface)(它管理数据模型调用);

所以,这是代码:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.EmotionsViewHolder> {
    @Inject
    DbHelper mDbHelper;
    @Inject
    Context mContext;

    private ArrayList<String> mItemsList;
    private DataSetChangeListener mDataSetChangeListener;
    private DataProviderListener mDataProviderListener;

    public RecyclerAdapter(DataProviderListener dataProviderListener, DataSetChangeListener listener) {
        App.getAppComponent().inject(this);
        //TODO: Replace with dagger 2 injection
        mDataSetChangeListener = listener;
        mDataProviderListener = dataProviderListener;
        mItemsList = dataProviderListener.getDataSet();
        notifyFragmentAboutDataSetStatus();
    }

    private void notifyFragmentAboutDataSetStatus() {
        if (mItemsList.size() == 0) {
            mDataSetChangeListener.notifyDataSetIsEmpty();
        } else {
            mDataSetChangeListener.notifyDataSetIsNotEmpty();
        }
    }

    @Override
    public EmotionsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cbt_element, parent, false);
        return new EmotionsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(EmotionsViewHolder holder, final int position) {
        holder.mEmotionsTextView.setText(mItemsList.get(position));
        holder.mEditImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                editItem(position);
            }
        });
        holder.mDeleteImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                removeItem(position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return mItemsList.size();
    }

    public void addItem(String item) {
        mItemsList.add(item);
        notifyItemInserted(mItemsList.size());
    }

    private void editItem(int position) {
        String currentValue = mItemsList.get(position);
        mDataProviderListener.callEditDialog(currentValue);
    }

    private void removeItem(int position) {
        String[] selectionArgs = new String[]{mItemsList.get(position)};
        mItemsList.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, mItemsList.size());

        Uri uri = UniquesContract.EmotionsEntity.CONTENT_URI;
        String selection = UniquesContract.EmotionsEntity.EMOTION_COL + " = ?";
        mContext.getContentResolver().delete(uri, selection, selectionArgs);
    }

    static class EmotionsViewHolder extends RecyclerView.ViewHolder {
        TextView mEmotionsTextView;
        ImageView mEditImageView;
        ImageView mDeleteImageView;

        public EmotionsViewHolder(View view) {
            super(view);
            mEmotionsTextView = (TextView) view.findViewById(R.id.emotion_text_view);
            mEditImageView = (ImageView) view.findViewById(R.id.edit_item_image_view);
            mDeleteImageView = (ImageView) view.findViewById(R.id.delete_item_image_view);
        }
    }

    public void setNewDataSet(ArrayList<String> list) {
        mItemsList = list;
    }


}

我意识到,理论上我可以注入(inject) DataSetChangeListenerDataProviderListener,但我该怎么做。也许,关键是关于创建一个新的范围?但我不知道如何使用它。如果我什至没有能力从 RecyclerAdapter 类引用这两个对象,我怎么能在 RecyclerAdapter 中实例化这两个对象。将实例作为构造函数的参数传递已经不是 DI。我应该在这里做什么?

最佳答案

使您的项目使用更多 Dagger 和依赖注入(inject)的所有更改都取决于您的整个项目结构!但是,如果你想注入(inject)这两个接口(interface),你可以为 RecyclerAdapter 编写一个提供者方法,并将这些接口(interface)注入(inject)到你的模块中:

@Provides
@Singleton
public RecyclerAdapter provideRecyclerAdapter(DataProviderListener dataProviderListener, DataSetChangeListener listener) {
    return new RecyclerAdapter(dataProviderListener, listener);
}

note that: another provider or your module constructor must provide these interfaces while injection.

您还可以通过向 RecyclerAdapter 构造函数添加 @Inject 注解来进行构造函数注入(inject),如下所示:

@Inject
public RecyclerAdapter(DataProviderListener dataProviderListener, DataSetChangeListener listener) {
        App.getAppComponent().inject(this);
        ...

你可以通过阅读我完成的这个示例项目来了解更多关于在 Android 项目中使用 dagger 的信息:

https://github.com/mmirhoseini/fyber_mobile_offers

关于android - 如何将 Activity 和 Fragment 注入(inject) RecyclerAdapter (Dagger 2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39972976/

相关文章:

java - 如何在构造函数中使用参数 Autowiring ?

android - 使用 dagger2 进行 Robolectric 测试 Activity

android - 什么时候可以在 OnMapReadyCallback 的 onMapReady 之后调用 GoogleMap.moveCamera?

c# - 使用 C# 进行依赖注入(inject) - 在哪里加载已解析对象的数据

android - 多列上的 GreenDao 主键

c# - DI 使用动态构造函数注入(inject)

android - 基类中的 ViewModelProviders.get(...)

AndroidInjector<android.app.Activity> 不能在没有 @Provides- 或 @Produces- 注释的方法的情况下提供

android - 隐藏 SD 卡上有照片的文件夹

java - 选择跟踪器实现