Home Converting Adapter onBindViewHolder itemView context to Class context with SQLite db
Reply: 1

Converting Adapter onBindViewHolder itemView context to Class context with SQLite db

seeking_stillness
1#
seeking_stillness Published in 2018-01-13 00:08:33Z

I have a working recycle view.

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

In the onBindViewHolder I check if the item is already saved and if so place a "saved" image on the card. I do this by cheking an ID value against already saved items in my SQLite db. 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?

To alleviate my concerns, I tried passing context through the constructor and making databaseHelper a class Object, but whatever context I passed caused my SQLite database method to crash in the databaseHelper Class. I tried passing Activity.this, application context, base context, etc. I've only been successful passing the viewHolder item context as shown. Like I said the code as written works, but I fear it is costly.

Here is the code I tried

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

Here is my SQLite method

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

Here is my error (that I only get with the code posted that passes context through the contructor). Otherwise it all works.

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
MikeT
2#
MikeT Reply to 2018-01-13 03:14:15Z

You could include the context via the constrcutor and then create an instance of the helper in the constructor.

e.g. Instead of :-

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

use :-

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

and remove the line :-

    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?

It's not the best way simply because you are re-constructing the instance. With regard to opening the database, that is actually done not at construction but when either getReableDatabase or getWriteableDatabase is called, which will be the same as that's done when the isSaved method is invoked. The get????ableDatabase are designed to cope with multiple invocations. So, I believe that there is little to be concerned about.

However, you don't close the Cursor in the isSaved method. This should be of concern as if you have too many Cursors open then an exception will occur.

You may want to change :-

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

to something like :-

//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;
}
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.604653 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO