Wai Yan Hein
Wai Yan Hein

Reputation: 14801

How to use or instantiate Sqlite Database Helper class instance inside a custom dapter class in Android?

I am absolute beginner to Android. Now I am creating a tutorial project. In my project I am using ListView with custom adapter. But I created the custom adapter as a different and standalone file to make my activity clean. But when I create it in a different file, I cannot use my database helper class inside the custom adapter.

The problem is I cannot pass the Activity context to the database helper class instance. In fragment, I can pass by calling this method.getActivity(). Then pass it to the constructor of my database helper class. How can I do the same thing in my custom adapter class?

This is my database helper class:

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "todo.db";
    private static final String TABLE_NAME = "task";
    private static final String COLUMN_ID = "id";
    private static final String COLUMN_DESCRIPTION = "description";
    private static final String COLUMN_DATE ="date";
    private static final String COLUMN_DONE = "done";
    private static final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+" ("+COLUMN_ID+" INTEGER PRIMARY KEY AUTOINCREMENT,"+COLUMN_DESCRIPTION+" TEXT,"+
    COLUMN_DATE+" DATE,"+COLUMN_DONE+" BOOLEAN)";
    SQLiteDatabase db;

    public DatabaseHelper(Context context)
    {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db)
    {
        this.db = db;
        db.execSQL(CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String query = "DROP TABLE IF EXISTS "+TABLE_NAME;
        db.execSQL(query);
        this.onCreate(db);
    }

    public  void insertTask(Task task)
    {
        db = getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(COLUMN_DESCRIPTION,task.getDescription());
        values.put(COLUMN_DATE,task.getDate());
        values.put(COLUMN_DONE, Boolean.FALSE.toString());
        db.insert(TABLE_NAME, null, values);
        db.close();
    }

    public ArrayList<Task> getAllTasks()
    {
        ArrayList<Task> items = new ArrayList<Task>();
        db = getReadableDatabase();
        String query = "SELECT * FROM "+TABLE_NAME;
        Cursor cursor = db.rawQuery(query,null);
        if(cursor.moveToFirst())
        {
            do{
                Task item = new Task();
                item.setId(cursor.getInt(0));
                item.setDescription(cursor.getString(1));
                item.setDate(cursor.getString(2));
                item.setDone(Boolean.valueOf(cursor.getString(3)));
                items.add(item);
            }
            while (cursor.moveToNext());
        }
        return items;
    }

    public void markAsDone(int id){
        db = getWritableDatabase();
        ContentValues updatedData = new ContentValues();
        updatedData.put(COLUMN_DONE, String.valueOf(Boolean.TRUE));
        String where = COLUMN_ID+" = "+String.valueOf(id);
        db.update(TABLE_NAME,updatedData,where,null);
    } 
}

This is my custom adapter class for listView (TaskListAdapter.java):

public class TaskListAdapter extends ArrayAdapter<Task> {
    private final Context context;
    private final ArrayList<Task> values;
    private DatabaseHelper dbHelper;
    public TaskListAdapter(Context context,ArrayList<Task> values)
    {
        super(context,-1,values);
        this.context = context;
        this.values = values;
    }

    @Override
    public View getView(int position,View convertView,ViewGroup parent)
    {
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView  = inflater.inflate(R.layout.task_list_row,parent, false);
        rowView.setTag(values.get(position).getId());
        TextView rowDescription = (TextView)rowView.findViewById(R.id.task_row_description);
        rowDescription.setText(values.get(position).getDescription());
        ImageView rowStatusIcon = (ImageView)rowView.findViewById(R.id.task_row_status_icon);

        Long currentDateMillSec= System.currentTimeMillis();
        Long dateMillSec = CommonHelper.convertStrDateToMilSec(values.get(position).getDate());//(date==null)?0:date.getTime();
        if(values.get(position).getDone()==Boolean.TRUE)
        {
           rowStatusIcon.setImageResource(R.drawable.done_icon);
        }
        else if(dateMillSec>0 && dateMillSec<currentDateMillSec)
        {
           rowStatusIcon.setImageResource(R.drawable.failed_icon);
        }
        else{
            rowStatusIcon.setImageResource(R.drawable.todo_icon);
        }


        TextView dateTf = (TextView)rowView.findViewById(R.id.task_row_date);
        dateTf.setText(values.get(position).getDate());

        Button doneBtn = (Button)rowView.findViewById(R.id.task_row_done_btn);
        doneBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //how can I instantiate the dbHelper class
                //Then use the merkAsDone method here
            }
        });
        return rowView;
    }


}

How can I instantiate the dbHelper property in my custom adapter and then call the markAsDone method in the done button click event. How can I achieve it whereas the adapter is not created within Activity?

Upvotes: 2

Views: 3415

Answers (3)

Mustansar Saeed
Mustansar Saeed

Reputation: 2790

You should make the DatabaseHelper class as thread-safe Singleton and then get that instance from the adapter.

public class DatabaseHelper extends SQLiteOpenHelper{
     private static DatabaseHelper dbHelper;

    public static DatabaseHelper getInstance() {
        if(dbHelper == null)
        {
            synchronized (DatabaseHelper.class)
            {
                if(dbHelper == null)
                {
                    dbHelper = new DatabaseHelper(MyApplicationInstance.getAppContext());
                }
            }
        }

        return dbHelper;
    }

    private DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
}

And then in the CustomAdapter just execute your commands as DatabaseHelper.getInstance().insert()

Hope this helps.

Upvotes: 0

J&#246;rn Buitink
J&#246;rn Buitink

Reputation: 2916

Does not look like a big problem, instantiate it in your constructor:

public TaskListAdapter(Context context,ArrayList<Task> values)
{
    super(context,-1,values);
    this.dbHelper = new DatabaseHelper(context.getApplicationContext());
    this.context = context;
    this.values = values;
}

Then use it in your OnClickListener:

Button doneBtn = (Button)rowView.findViewById(R.id.task_row_done_btn);
doneBtn.setTag(values.get(position).getId());
doneBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        dbHelper.markAsDone(v.getTag());
    }
});

Don't forget to close your Database in DatabaseHelper.markAsDone

Upvotes: 3

S. Alawadi
S. Alawadi

Reputation: 144

Firstly if you want to use the db inside the adapter , you can use CursorAdapter not ArrayAdapter ,

if you want to stay on arrayAdapter , then you can pass th db Object in the construcor

Upvotes: 0

Related Questions