使用SQLite数据库将适配器onBindViewHolder itemView上下文转换为Class上下文

android sqlite android-recyclerview adapter android-context

122 观看

1回复

2136 作者的声誉

我有一个工作循环视图:

public class MtbListAdapter extends RecyclerView.Adapter<MtbListAdapter.RecyclerViewHolder> implements Filterable {
private ArrayList<ApiObject> arrayList;
private ArrayList<ApiObject> arrayListFiltered;
private DatabaseHelper databaseHelper;

public MtbListAdapter(ArrayList<ApiObject> arrayList) {
    this.arrayList =arrayList;
    this.arrayListFiltered =arrayList;
}

@Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_mtb, viewGroup, false);
    return new RecyclerViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerViewHolder recyclerViewHolder, int position){

    //load texts to card
    recyclerViewHolder.tv_name.setText(arrayListFiltered.get(position).getName());
    recyclerViewHolder.tv_length.setText(arrayListFiltered.get(position).getLength());

    //is card already saved?
    String s_identifier = arrayListFiltered.get(position).getId();
    databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext());
    boolean isSaved = databaseHelper.isSaved(s_identifier);

    if (isSaved) recyclerViewHolder.iv_isSaved.setVisibility(View.VISIBLE);
    else recyclerViewHolder.iv_isSaved.setVisibility(View.INVISIBLE);
}

onBindViewHolderI中检查项目是否已经保存,如果是,则在卡片上放置“已保存”的图像。我这样做是通过在我的SQLite数据库中为已保存的项目获取ID值。我关心的一件事就是databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext());被召唤了很多。问题1.这是一个问题吗?

为了缓解我的顾虑,我尝试通过构造函数传递上下文并使databaseHelper成为一个类Object,但是我传递的任何上下文都导致我的SQLite数据库方法在databaseHelper类中崩溃。我尝试传递Activity.this,应用程序上下文,基本上下文等。我只是成功传递了viewHolder项目上下文,如图所示。就像我说代码作为书面作品,但我担心它代价高昂。

这是我试过的代码:

 public class MtbListAdapter extends RecyclerView.Adapter<MtbListAdapter.RecyclerViewHolder> implements Filterable {
    private Context context;
    private ArrayList<ApiObject> arrayList;
    private ArrayList<ApiObject> arrayListFiltered;
    private DatabaseHelper databaseHelper = new DatabaseHelper(context);

public MtbListAdapter(ArrayList<ApiObject> arrayList, Context context) {
    this.arrayList =arrayList;
    this.arrayListFiltered =arrayList;
    this.context =context;
}

@Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_mtb, viewGroup, false);
    return new RecyclerViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerViewHolder recyclerViewHolder, int position){

    //load texts to card
    recyclerViewHolder.tv_name.setText(arrayListFiltered.get(position).getName());
    recyclerViewHolder.tv_length.setText(arrayListFiltered.get(position).getLength());

    //is card already saved?
    String s_identifier = arrayListFiltered.get(position).getId();
    boolean isSaved = databaseHelper.isSaved(s_identifier);

    if (isSaved) recyclerViewHolder.iv_isSaved.setVisibility(View.VISIBLE);
    else recyclerViewHolder.iv_isSaved.setVisibility(View.INVISIBLE);
}

这是我的SQLite方法:

 //returns true if is already saved
public boolean isSaved(String s) {
    SQLiteDatabase db = getReadableDatabase();
    String[] columns = new String[] {KEY_IDENTIFIER};
    String where = KEY_IDENTIFIER + " = ?";
    String[] whereArgs = new String[] {s};

    // select column_word from table where column_word = 's' limit 1;
    try (Cursor c = db.query(TABLE_NAME, columns, where, whereArgs, null, null, null, "1")){
        return c.moveToFirst();
    }
}

这是我的错误(我只得到发布的代码,通过构造函数传递上下文)。否则一切正常。

java.lang.NullPointerException:尝试调用虚方法'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String,int,android.database.sqlite.SQLiteDatabase $ CursorFactory,android.database.DatabaseErrorHandler )'在空对象引用上

作者: seekingStillness 的来源 发布者: 2018 年 1 月 13 日

回应 1


1

22825 作者的声誉

决定

您可以通过constrcutor 包含上下文,然后在构造函数中创建帮助程序的实例。

例如,而不是: -

public MtbListAdapter(ArrayList<ApiObject> arrayList) {
    this.arrayList =arrayList;
    this.arrayListFiltered =arrayList;
}

使用 :-

public MtbListAdapter(Context context, ArrayList<ApiObject> arrayList) {
    this.arrayList =arrayList;
    this.arrayListFiltered =arrayList;
    databaseHelper = new DatabaseHelper(context);
}

并删除该行: -

    databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext());

我关心的一件事是databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext()); 被召唤了很多。问题1.这是一个问题吗?

这不是最好的方法,因为你正在重新构建实例。对于打开数据库,这实际上是做不建设,但无论是时getReableDatabase还是getWriteableDatabase被调用,这将是相同的时的完成isSaved方法被调用。get ???? ableDatabase旨在处理多个调用。所以,我认为没有什么值得关注的。

但是,您不要关闭isSaved方法中的Cursor 。这应该是值得关注的,好像你有太多的游标打开然后会发生异常。

你可能想要改变: -

//returns true if is already saved
public boolean isSaved(String s) {
    SQLiteDatabase db = getReadableDatabase();
    String[] columns = new String[] {KEY_IDENTIFIER};
    String where = KEY_IDENTIFIER + " = ?";
    String[] whereArgs = new String[] {s};

    // select column_word from table where column_word = 's' limit 1;
    try (Cursor c = db.query(TABLE_NAME, columns, where, whereArgs, null, null, null, "1")){
        return c.moveToFirst();
    }
}

之类的: -

//returns true if is already saved
public boolean isSaved(String s) {
    boolean rv = false;
    SQLiteDatabase db = getReadableDatabase();
    String[] columns = new String[] {KEY_IDENTIFIER};
    String where = KEY_IDENTIFIER + " = ?";
    String[] whereArgs = new String[] {s};

    // select column_word from table where column_word = 's' limit 1;
    (Cursor c = db.query(TABLE_NAME, columns, where, whereArgs, null, null, null, "1"));
    if(c.moveToFirst) {
            rv = true;
    }
    c.close()
    return rv;
}
作者: MikeT 发布者: 2018 年 1 月 13 日
32x32