Access SQLite Helper From Adapter - java

Code
public class ChatData extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "MessagePlus";
public ChatData(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public Cursor getAllQuestions3(MessagesAdapter usageSettings2) {
return this.getWritableDatabase().query(TABLE_CHAT_DATA,null,null,null,null,null,null);
}
}
Adapter
final ChatData mHelper = new ChatData(this);
final Cursor csr = mHelper.getAllQuestions3(this);
Nothing is working for context in adapter. This shows message to change the Helper classes context to the Adapters name and if i do that theres a red line under context in the helper... If i directly try to access like ChatData.getWritableDatabase it shows that u cant access a non static method from a static class and if i make that method in helper static it shows error there saying class cant be static... one error is leading to another and i dont know what to do so can someone help me out please
EDIT
Full Adapter Code
public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MessageViewHolder>{
private List<SQLiteHelper> mMessagesHelperList;
private FirebaseAuth mAuth;
ChatData mHelper = new ChatData(this);
Cursor csr = mHelper.getAllQuestions3();
public MessagesAdapter(List<SQLiteHelper> mMessagesHelperList) {
this.mMessagesHelperList = mMessagesHelperList;
}
public class MessageViewHolder extends RecyclerView.ViewHolder{
public TextView messageText;
public MessageViewHolder(View view) {
super(view);
messageText = (TextView)view.findViewById(R.id.message_text_layout);
}
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View V = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_activity_chat,parent,false);
mAuth = FirebaseAuth.getInstance();
return new MessageViewHolder(V);
}
#Override
public void onBindViewHolder(final MessageViewHolder holder, int position) {
String mSender = null;
String mMessage = null;
String mTime;
String mSeen = null;
String mTimer;
String mType;
while (csr.moveToNext()) {
mSender = csr.getString(csr.getColumnIndex(KEY_SENDER));
mMessage = csr.getString(csr.getColumnIndex(KEY_MESSAGE));
mTime = csr.getString(csr.getColumnIndex(KEY_TIME));
mSeen = csr.getString(csr.getColumnIndex(KEY_SEEN));
mTimer = csr.getString(csr.getColumnIndex(KEY_TIMER));
mType = csr.getString(csr.getColumnIndex(KEY_TYPE));
}
SQLiteHelper messagesHelper = mMessagesHelperList.get(position);
#Override
public int getItemCount() {
return mMessagesHelperList.size();
}
}
Activity
final MainData mHelper = new MainData(this); //Change the name to your Helper Class name
final Cursor csr = myDBHlpr.getAllQuestions3(this);
messageList.setAdapter(mAdapter);
while (csr.moveToNext()) {
String mSender = csr.getString(csr.getColumnIndex(KEY_SENDER));
String mMessage = csr.getString(csr.getColumnIndex(KEY_MESSAGE));
String mTime = csr.getString(csr.getColumnIndex(KEY_TIME));
String mSeen = csr.getString(csr.getColumnIndex(KEY_SEEN));
String mTimer = csr.getString(csr.getColumnIndex(KEY_TIMER));
String mType = csr.getString(csr.getColumnIndex(KEY_TYPE));
messages.add(new SQLiteHelper(mSender, mMessage, mTime, mSeen, mTimer, mType));
}

The following will likely cause some of your issues. That is you are saying that the method should be passed a MesagesAdapter, when as it stands there is no reason to pass anything into the getAllQuestions3 method.
public Cursor getAllQuestions3(MessagesAdapter usageSettings2) {
return this.getWritableDatabase().query(TABLE_CHAT_DATA,null,null,null,null,null,null);
}
Trying changing the above to
public Cursor getAllQuestions3() {
return this.getWritableDatabase().query(TABLE_CHAT_DATA,null,null,null,null,null,null);
}
and use
ChatData mHelper = new ChatData(this);
Cursor csr = mHelper.getAllQuestions3();
instead of
final ChatData mHelper = new ChatData(this,ChatData.DATABASE_NAME,null,ChatData.DATABASE_VERSION);
final Cursor csr = mHelper.getAllQuestions3(this);
Noting that the above lines should be in the Activity's onCreate method or a method invoked from onCreate so that you have a valid context (i.e. this).
Edit 1
Note that the above has been changed as according to ChatData you need to provided 4 parameters for the instantiation of a ChatData object.
I'd suggest changing the constructor to :-
public ChatData(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
and then you could use ChatData mHelper = new ChatData(this);.
Working Example
The following is a working example based upon the code you have given.
The database helper ChatData.java
public class ChatData extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "MessagePlus";
public static final String TABLE_CHAT_DATA = "chatdata";
public static final String COL_CHATDATA_ID = BaseColumns._ID;
public static final String COL_CHATDATA_TIMESTAMP = "timestamp";
public static final String COL_CHATDATA_MESSAGE = "message";
public static final String COL_CHATDATA_USER = "user";
public ChatData(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String crt_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_CHAT_DATA + "(" +
COL_CHATDATA_ID + " INTEGER PRIMARY KEY, " +
COL_CHATDATA_TIMESTAMP + " TEXT DEFAULT CURRENT_TIMESTAMP," +
COL_CHATDATA_MESSAGE + " TEXT, " +
COL_CHATDATA_USER + " INTEGER" +
")";
db.execSQL(crt_sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public Cursor getAllQuestions3() {
return this.getWritableDatabase().query(TABLE_CHAT_DATA,null,null,null,null,null,null);
}
public long addMessage(String message, long user) {
ContentValues cv = new ContentValues();
cv.put(COL_CHATDATA_MESSAGE,message);
cv.put(COL_CHATDATA_USER,user);
SQLiteDatabase db = this.getWritableDatabase();
return db.insert(TABLE_CHAT_DATA,null,cv);
}
}
Note modified to crate a table and to allow rows to be added to the table.
Note the constructor.
The Custom Adapter (Cursor Adapter) MessageAdapter.java
public class MessageAdapter extends CursorAdapter {
public MessageAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View rv = LayoutInflater.from(context).inflate(
R.layout.messagelist_item,
parent,
false
);
return rv;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView mUser = view.findViewById(R.id.user);
TextView mTimestamp = view.findViewById(R.id.timestamp);
TextView mMessage = view.findViewById(R.id.message);
mUser.setText(cursor.getString(cursor.getColumnIndex(ChatData.COL_CHATDATA_USER)));
mTimestamp.setText(cursor.getString(cursor.getColumnIndex(ChatData.COL_CHATDATA_TIMESTAMP)));
mMessage.setText(cursor.getString(cursor.getColumnIndex(ChatData.COL_CHATDATA_MESSAGE)));
}
}
The layout used in the list messagelist_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/user"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/timestamp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/message"
android:layout_width="0dp"
android:layout_weight="8"
android:layout_height="wrap_content" />
</LinearLayout>
The code in the Activity to list the messages via the adapter (MainActivty.java)
public class MainActivity extends AppCompatActivity {
ChatData mDBHlpr;
Cursor mCsr;
MessageAdapter mMesaageAdapter;
ListView mMessageList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessageList = this.findViewById(R.id.messagelist);
mDBHlpr = new ChatData(this);
addSomeData();
mCsr = mDBHlpr.getAllQuestions3();
mMesaageAdapter = new MessageAdapter(this,mCsr,false);
mMessageList.setAdapter(mMesaageAdapter);
}
private void addSomeData() {
mDBHlpr.addMessage("Hello",1);
mDBHlpr.addMessage("Hi",2);
mDBHlpr.addMessage("How are you?",1);
mDBHlpr.addMessage("I'm OK thanks, and you?",2);
mDBHlpr.addMessage("Good.",1);
}
}
Result

Related

Android studio displaying data from sqlite local db

I cant seem to find any solutions to this problem on the internet. basically im working on an app that lets the user create workouts and view them and I'm struggling with the view part.
My database is all set up with user input using the fields exercise, sets and reps, the user creates a workout and the contents of the table used to build it are copied to a new one and the table is cleared to take in new input.
I want to create a recycler view using the table names, pass the selected item name to the next fragment and use the users selection to determine what data will be shown in the next recycler view.
Is this possible and if so please show me how, I'm supposed to have this app ready in a couple of days for an assignment
any help would be appreciated, thanks - Ian
To clairfy, you would like to make list of the list?
Use one to many relationship or map using room.
I have done such implementation days ago feel free to ask.
https://developer.android.com/training/data-storage/room/relationships?fbclid=IwAR3P_rK8OeOpBpP9jgbL8FqxEKPXPvOaFwFiCMy4pIpblg_aF_9QloavHpM
https://developer.android.com/training/data-storage/room/relationships?fbclid=IwAR22XINRNxTs3b_KOleeYwjGuIwjUA90S3tvpMWkf1dKYjvDDo5qWAbLfoE
To get previous ID or name just use simple Bundle of position(or ID) of specific element from first recyclerview and use it in the second to display the right data.
Is this possible and if so please show me how.
It is possible.
Here's a working demo that shows how.
First the class that extends SQLiteOPenHelper, as is typically used, namely DatabaseHelper in this example:-
class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "thedatabase.db";
public static final int DATABASE_VERSION = 1;
private SQLiteDatabase db;
private DatabaseHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
db = this.getWritableDatabase();
}
private static volatile DatabaseHelper instance = null;
public static DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context);
}
return instance;
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(MyTable.CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase db, int old_version, int new_version) {
}
public long insertMyTableRow(Long id, String item_name) {
ContentValues cv = new ContentValues();
cv.put(MyTable.COL_ITEM_NAME,item_name);
if (id != null && id == 0) {
cv.put(MyTable.COl_ID,id);
}
return db.insertWithOnConflict(MyTable.TABLE_NAME,null,cv,SQLiteDatabase.CONFLICT_IGNORE);
}
#SuppressLint("Range")
public MyTable[] getAllMyTableRowAsArrayOfMyTable() {
MyTable[] rv = new MyTable[0];
Cursor csr = db.query(MyTable.TABLE_NAME,null,null,null,null,null,null);
if (csr.getCount() > 0) {
rv = new MyTable[csr.getCount()];
}
int idx = 0;
while (csr.moveToNext()) {
rv[idx++] = new MyTable(
csr.getLong(csr.getColumnIndex(MyTable.COl_ID)),
csr.getString(csr.getColumnIndex(MyTable.COL_ITEM_NAME)
)
);
}
csr.close();
return rv;
}
#SuppressLint("Range")
public MyTable getAMyTableById(long id) {
MyTable rv = new MyTable(-1,"NOT FOUND");
Cursor csr = db.query(MyTable.TABLE_NAME,null,MyTable.COl_ID+"=?",new String[]{String.valueOf(id)},null,null,null);
if (csr.moveToFirst()) {
rv = new MyTable(csr.getLong(csr.getColumnIndex(MyTable.COl_ID)),csr.getString(csr.getColumnIndex(MyTable.COL_ITEM_NAME)));
}
csr.close();
return rv;
}
}
class MyTable {
public static final String TABLE_NAME = (MyTable.class.getSimpleName()).toLowerCase();
public static final String COl_ID = TABLE_NAME + BaseColumns._ID;
public static final String COL_ITEM_NAME = TABLE_NAME + "_item_name";
// and so on
public static final String CREATE_SQL = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"("
+ COl_ID + " INTEGER PRIMARY KEY"
+ "," + COL_ITEM_NAME + " TEXT UNIQUE "
// and so on
+ ")";
long id;
String itemName;
MyTable(long id, String item_name) {
this.id = id;
this.itemName = item_name;
}
}
The activity that will be called MainActivity2 being passed a unique identifier of the clicked item via an Intent Extra :-
public class MainActivity2 extends AppCompatActivity {
public static final String INTENT_EXTRA_MYTABLE_ID = "ie_mytable_id";
DatabaseHelper dbHelper;
TextView itemName;
Button done;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
itemName = this.findViewById(R.id.item_name);
done = this.findViewById(R.id.done);
dbHelper = DatabaseHelper.getInstance(this);
itemName.setText((dbHelper.getAMyTableById(this.getIntent().getLongExtra(INTENT_EXTRA_MYTABLE_ID,-99))).itemName);
done.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
}
}
An Adapter TheAdapter etc for the RecyclerView, including Item Click and Item Long Click listeners. Clicking an item Toasts details. Long clicking starts the second activity which displays the clicked item:-
public class TheAdapter extends RecyclerView.Adapter<TheAdapter.ViewHolder> {
private MyTable[] localData;
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView1;
private final TextView textView2;
public ViewHolder(View view) {
super(view);
textView1 = (TextView) view.findViewById(android.R.id.text1);
textView2 = (TextView) view.findViewById(android.R.id.text2);
}
public TextView getTextView1() {
return textView1;
}
public TextView getTextView2() {
return textView2;
}
}
public TheAdapter(MyTable[] thedata) {
localData = thedata;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.getTextView1().setText(String.valueOf(localData[position].id));
holder.getTextView2().setText(localData[position].itemName);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(
view.getContext(),
"You clicked the Item named "
+ localData[holder.getAdapterPosition()].itemName
+ " the ID is " + String.valueOf(localData[holder.getAdapterPosition()].id),
Toast.LENGTH_SHORT
).show();
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
Intent intent = new Intent(view.getContext(),MainActivity2.class);
intent.putExtra(MainActivity2.INTENT_EXTRA_MYTABLE_ID,localData[holder.getAdapterPosition()].id);
view.getContext().startActivity(intent);
return true;
}
});
}
#Override
public int getItemCount() {
return localData.length;
}
}
Finally the first/initial activity MainActivity :-
public class MainActivity extends AppCompatActivity {
DatabaseHelper dbHelper;
RecyclerView myTableList;
TheAdapter adapter;
MyTable[] theDataToBeDisplayed;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTableList = this.findViewById(R.id.mytable_list);
dbHelper = DatabaseHelper.getInstance(this);
addSomeTestingData();
setupOrRefreshMyTableList();
}
private void setupOrRefreshMyTableList() {
theDataToBeDisplayed = dbHelper.getAllMyTableRowAsArrayOfMyTable();
if (adapter == null) {
adapter = new TheAdapter(theDataToBeDisplayed);
myTableList.setAdapter(adapter);
myTableList.setLayoutManager(
new LinearLayoutManager(this)
);
} else {
/* handle changed data here */
}
}
private void addSomeTestingData() {
for (int i=0; i < 100; i++) {
dbHelper.insertMyTableRow(null, "A" + String.valueOf(i));
}
}
}
When run:-
When an Item (e.g. A10 (whos' id is 11)) is Long clicked :-
Clicking DONE returns to the first activity.

How do I delete data from SQLITE database by ID

I am having a lot of trouble finding out how to delete data from my sqlite database by using ID.
How do I delete data from my sqlite databse by using ID?
final ItemTouchHelper.SimpleCallback itemTouchHelper = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
list.remove(viewHolder.getAdapterPosition());
adapter.notifyDataSetChanged();
/////// I want to delete this data from my sqlite Data Base by using it's id. But how do I get the id?///////
}
};
Should that be done in the OnBindViewHolder?
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.notePadTextView.setText(arrayListNote.get(position).getNote());
}
This is my custom adapter:
public class NotesCustomAdapter extends RecyclerView.Adapter{
private ArrayList arrayListNote;
private Context context;
public NotesCustomAdapter(ArrayList<newNote> arrayListNote, Context context) {
this.arrayListNote = arrayListNote;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.notepad_model,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.notePadTextView.setText(arrayListNote.get(position).getNote());
}
#Override
public int getItemCount() {
return arrayListNote.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
LinearLayout NotePadMode;
TextView notePadTextView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
NotePadMode= itemView.findViewById(R.id.NotePadModel);
notePadTextView = itemView.findViewById(R.id.notePadTextView);
}
}
}
This is my SQlite Database:
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String DATABSE_NAME = "AllWorkHours.db";
public static final String TABLE_NAME = "ALLWORKHOURS";
public static final String COL_0 = "ID";
public static final String COL_1 = "DATE";
public static final String COL_2 = "TIMESHIFTSTART";
public static final String COL_3 = "TIMESHIFTENDS";
public static final String COL_4 = "NOTES";
public static final String COL_5 = "NOTEMEMOS";
public static final int DATABASE_Version = 5;
public DataBaseHelper(Context context) {
super(context, DATABSE_NAME,null,DATABASE_Version);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, DATE TEXT, TIMESHIFTSTART INTEGER, TIMESHIFTENDS TEXT, NOTES TEXT, NOTEMEMOS TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS ALLWORKHOURS");
onCreate(db);
}
public boolean addHours(String Date, String TimeShiftStart, String TimeShiftEnds, String Notes){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_1, Date);
contentValues.put(COL_2, TimeShiftStart);
contentValues.put(COL_3, TimeShiftEnds);
contentValues.put(COL_4, Notes);
long inserted = db.insert(TABLE_NAME,null,contentValues);
if (inserted == -1){
return false;
}else{
return true;
}
}
public ArrayList<newShift> viewAllHours(){
ArrayList<newShift> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String Date = cursor.getString(1);
String timestart = cursor.getString(2);
String timeEnds = cursor.getString(3);
String notes = cursor.getString(4);
newShift newShift = new newShift(id,Date,timestart,timeEnds,notes);
arrayList.add(newShift);
}
return arrayList;
}
public boolean addNotes(String NOTEMEMOS) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_5, NOTEMEMOS);
long inserted = db.insert(TABLE_NAME, null, contentValues);
if (inserted == -1){
return false;
}else{
return true;
}
}
public ArrayList<newNote> ViewAllNotes() {
ArrayList<newNote> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT NOTEMEMOS FROM " + TABLE_NAME, null);
while(cursor.moveToNext()){
String notes = cursor.getString(0);
newNote newnote = new newNote(notes);
arrayList.add(newnote);
}
return arrayList;
}
}
You can try this
db.delete(table, whereClause, whereArgs)
after delete entry, refresh your view (listview)
You have to get Id of your model before remove like:
newShift obj = list.get(viewHolder.getAdapterPosition());
DataBaseHelper _yourdatabaseObject = youtDatabaseInstance();
_yourdatabaseObject.removeDataByID(""+obj.id);
list.remove(viewHolder.getAdapterPosition());
adapter.notifyDataSetChanged();
Make A function Of delete note in DataBaseHelper.
public void deleteMyNote(String id){
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("delete from "+ TABLE_NAME +" where ID='"+ id +"'");
}

get the data when an Item is clicked in recyclerview

How to access data after clicking an Item of RecyclerView. What I need is the logic behind on how to get the expanded Items from the database.
Currently for adapter using CursorRecyclerViewAdapter to get data from database https://gist.github.com/skyfishjy/443b7448f59be978bc59
RemindersAdapter.java
public class RemindersAdapter extends CursorRecyclerViewAdapter<RemindersAdapter.ItemViewHolder> {
private final LayoutInflater inflater;
List<ListInfo> data = Collections.emptyList();
private Context context;
ListInfo temporaryBucket;
public RemindersAdapter(Context context, Cursor cursor){
super(context, cursor);
inflater = LayoutInflater.from(context);
this.context = context;
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.reminder_item, parent, false);
ItemViewHolder holder = new ItemViewHolder(view);
temporaryBucket = new ListInfo();
return holder;
}
#Override
public void onBindViewHolder(ItemViewHolder viewHolder, Cursor cursor) {
int id = cursor.getInt(cursor.getColumnIndex(MyDBHandler.COLUMN_ID));
String title = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_TITLE_REMINDER));
String desc = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_DESC_REMINDER));
String date = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_DATE_REMINDER));
viewHolder.title.setText(title);
}
class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title;
public ItemViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.reminderTitle);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getLayoutPosition();
Toast.makeText(context, "Clicked", Toast.LENGTH_SHORT).show();
}
}
}
MyDBHandler.java
public class MyDBHandler extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 7;
private static final String DATABASE_NAME = "paroah.db";
public static final String TABLE_REMINDER = "reminders";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_TITLE_REMINDER = "title";
public static final String COLUMN_DESC_REMINDER = "desc";
public static final String COLUMN_DATE_REMINDER = "date_created";
private Cursor allReminders;
public MyDBHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query = " CREATE TABLE "
+TABLE_REMINDER+ "(" +
COLUMN_ID +" INTEGER PRIMARY KEY AUTOINCREMENT,"+
COLUMN_TITLE_REMINDER + " TEXT ,"+
COLUMN_DESC_REMINDER + " TEXT ,"+
COLUMN_DATE_REMINDER + " TEXT "+
");";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d("aoi", "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
try {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_REMINDER);
onCreate(db);
} catch (SQLException e) {
Log.d("aoi", "getting exception "
+ e.getLocalizedMessage().toString());
}
}
public void addReminder(ListInfo reminder ){
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE_REMINDER, reminder.getTitle());
values.put(COLUMN_DESC_REMINDER, reminder.getDesc());
values.put(COLUMN_DATE_REMINDER, reminder.getDate());
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_REMINDER, null, values);
db.close();
}
public Cursor getAllReminders() {
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM "+TABLE_REMINDER;
allReminders = db.rawQuery(query, null);
return allReminders;
}
}
In my onBindViewHolder I'm getting "id, title, desc and date" but only showing the title which when clicked will show the desc and date. For testing just showing a Toast for now on click of item.
You can set the onClickListener in onBindViewHolder() with holder.itemView.setOnClickListener(new OnClickListener({...}), and you can access all data you need.
You can bind view holder with all the data even if you just show the title
#Override
public void onBindViewHolder(ItemViewHolder viewHolder, Cursor cursor) {
int id = cursor.getInt(cursor.getColumnIndex(MyDBHandler.COLUMN_ID));
String title = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_TITLE_REMINDER));
String desc = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_DESC_REMINDER));
String date = cursor.getString(cursor.getColumnIndex(MyDBHandler.COLUMN_DATE_REMINDER));
viewHolder.bind(id, title, desc, date);
}
class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
int idData;
String titleData;
String descData;
String dateData;
TextView title;
public ItemViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.reminderTitle);
itemView.setOnClickListener(this);
}
public void bind(int id, String title, String desc, String date){
this.idData = id;
this.titleData = title;
this.descData = desc;
this.dateData = date;
this.title.setText(title);
}
#Override
public void onClick(View v) {
// You can access all the data here
Toast.makeText(context, "Clicked", Toast.LENGTH_SHORT).show();
}
}
}

Custom list view in android giving error while updating data from database in android

I am trying to add check box and some text view (text view is getting value from database) in customized list view but it is giving error of NullPointerException. I don't know why and what is wrong with my code. Below is my code.
My MainActivity Class:
public class Classes extends Activity {
ImageView imageViewNewClass;
ListView mListView;
String[] stg1;
List<String[]> names2 = null;
DataManipulatorClass dataManipulator;
CustomAdapter customAdapter;
public Classes classes = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.classes);
imageViewNewClass = (ImageView) findViewById(R.id.newclass);
mListView = (ListView) findViewById(R.id.displaydata);
imageViewNewClass.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Classes.this, Class_Create.class);
startActivity(intent);
}
});
Resources res =getResources();
classes = this;
dataManipulator = new DataManipulatorClass(this);
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg = null;
for (String[] name : names2) {
stg = "Class Name : " + name[1];
stg1[x] = stg;
x++;
}
customAdapter= new CustomAdapter( classes, stg1,res );
mListView.setAdapter( customAdapter );
customAdapter.notifyDataSetChanged();
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View item,
int position, long id) {
Toast.makeText(getApplicationContext(),
"Listview item clicked", Toast.LENGTH_LONG).show();
}
});
}
}
CustomAdapterClass.java
public class CustomAdapter extends BaseAdapter {
/*********** Declare Used Variables *********/
private Activity activity;
private String[] data;
private static LayoutInflater inflater = null;
public Resources res;
int i = 0;
String[] stg1;
List<String[]> names2 = null;
DataManipulatorClass dataManipulator;
/************* CustomAdapter Constructor *****************/
public CustomAdapter(Activity a, String[] stg1, Resources resLocal) {
/********** Take passed values **********/
activity = a;
data = stg1;
res = resLocal;
/*********** Layout inflator to call external xml layout () ***********/
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/******** What is the size of Passed Arraylist Size ************/
public int getCount() {
if (data.length <= 0)
return 1;
return data.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
public CheckBox checkBox;
public TextView textView;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.check, null);
holder = new ViewHolder();
holder.checkBox = (CheckBox) vi.findViewById(R.id.checkBox1);
holder.textView = (TextView) vi.findViewById(R.id.selection);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
if (data.length <= 0) {
holder.textView.setText("No Data");
} else {
dataManipulator = new DataManipulatorClass(this);
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg = null;
for (String[] name : names2) {
stg = "Class Name : " + name[1];
stg1[x] = stg;
x++;
}
holder.textView.setText(stg1[x]);
}
return vi;
}
public void onClick(View v) {
Log.v("CustomAdapter", "=====Row button clicked=====");
}
}
DataManipulator.Java
public class DataManipulatorClass {
private static final String DATABASE_NAME = "mydatabaseclass.db";
private static final int DATABASE_VERSION = 1;
static final String TABLE_NAME = "newtableclass";
private static Context context;
static SQLiteDatabase db;
private SQLiteStatement insertStmt;
private static final String INSERT = "insert into " + TABLE_NAME
+ "(classname) values (?)";
public DataManipulatorClass(Context context) {
DataManipulatorClass.context = context;
OpenHelper openHelper = new OpenHelper(DataManipulatorClass.context);
DataManipulatorClass.db = openHelper.getWritableDatabase();
this.insertStmt = DataManipulatorClass.db.compileStatement(INSERT);
}
public DataManipulatorClass(CustomAdapter customAdapter) {
OpenHelper openHelper = new OpenHelper(DataManipulatorClass.context);
DataManipulatorClass.db = openHelper.getWritableDatabase();
this.insertStmt = DataManipulatorClass.db.compileStatement(INSERT);
}
public long insert(String classname) {
this.insertStmt.bindString(1, classname);
return this.insertStmt.executeInsert();
}
public void deleteAll() {
db.delete(TABLE_NAME, null, null);
}
public List<String[]> selectAll() {
List<String[]> list = new ArrayList<String[]>();
Cursor cursor = db.query(TABLE_NAME,
new String[] { "id", "classname" }, null, null, null, null,
"classname asc");
int x = 0;
if (cursor.moveToFirst()) {
do {
String[] b1 = new String[] { cursor.getString(0),
cursor.getString(1) };
list.add(b1);
x = x + 1;
} while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
cursor.close();
return list;
}
public void delete(int rowId) {
db.delete(TABLE_NAME, null, null);
}
private static class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "
+ TABLE_NAME
+ " (id INTEGER PRIMARY KEY, classname TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
}
In Classes Class I have listview in which i want to show the data, My logcat is here http://i.share.pho.to/9739fdca_o.png
It is giving error on mListView.setAdapter( customAdapter ); this line while setting adapter in listview as a customadapter...
Thanks in advance...
public class Classes extends Activity {
ImageView imageViewNewClass;
ListView mListView;
String[] stg1; // Never Initialized in code before passing to Adapter
// stg1, this variable you have never initialized in your activity, you are passing it Null to your custom adapter, thats why listview while accessing count of data throwing NPE vai adapter.
public int getCount() { // Will always be Null, as data is null
if (data.length <= 0)
return 1;
return data.length;
}
Just pass a not null instance of variable in activity and your problem will be resolved.
You replace
if (data.length <= 0) return 1;
to
if (data == null || data.length == 0) return 1;

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?
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
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
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.

Categories