使用 SQLite 数据库将 Adapter onBindViewHolder itemView 上下文转换为 Class 上下文
Converting Adapter onBindViewHolder itemView context to Class context with SQLite database
我有一个工作回收视图:
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);
}
在 onBindViewHolder
中,我检查该项目是否已保存,如果已保存,则将 "saved" 图像放在卡片上。我通过检查我的 SQLite 数据库中已保存的项目的 ID 值来做到这一点。我担心的一件事是 databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext());
被调用了很多次。问题 1. 这是一个问题吗?
为了减轻我的顾虑,我尝试通过构造函数传递上下文并使 databaseHelper 成为一个 class 对象,但是无论我传递什么上下文都会导致我的 SQLite 数据库方法在 databaseHelper Class 中崩溃。我尝试传递 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: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
您可以通过构造函数包含 context,然后在构造函数中创建助手实例。
例如而不是:-
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());
One thing I'm concerned about is that databaseHelper = new
DatabaseHelper(recyclerViewHolder.tv_name.getContext()); gets called a
lot. Question 1. Is this a concern?
这不是最好的方法,因为您正在重新构建实例。关于打开数据库,这实际上不是在构造时完成的,而是在调用 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;
}
我有一个工作回收视图:
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);
}
在 onBindViewHolder
中,我检查该项目是否已保存,如果已保存,则将 "saved" 图像放在卡片上。我通过检查我的 SQLite 数据库中已保存的项目的 ID 值来做到这一点。我担心的一件事是 databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext());
被调用了很多次。问题 1. 这是一个问题吗?
为了减轻我的顾虑,我尝试通过构造函数传递上下文并使 databaseHelper 成为一个 class 对象,但是无论我传递什么上下文都会导致我的 SQLite 数据库方法在 databaseHelper Class 中崩溃。我尝试传递 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: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
您可以通过构造函数包含 context,然后在构造函数中创建助手实例。
例如而不是:-
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());
One thing I'm concerned about is that databaseHelper = new DatabaseHelper(recyclerViewHolder.tv_name.getContext()); gets called a lot. Question 1. Is this a concern?
这不是最好的方法,因为您正在重新构建实例。关于打开数据库,这实际上不是在构造时完成的,而是在调用 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;
}