Android - Deleting database entries using cursor - java

I'm looking to add a new feature to my BETA version of my application.I think I need help on my approach to handling deleting a specific row.
I've been able to do everything I want with the databases in my app except for deleting a particular row or ID value from both database tables.
I'm calling a deleteClient() and passing the cursor in my DBAdapter. This table takes a long value for the rowID.
DBAdapter:
public boolean deleteClient(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
DatabaseHandler creates a second database for other storage work but should delete the same:
public boolean delete(long rowId)
{
return db.delete(TABLE_LABELS, KEY_ID + "=" + rowId, null) > 0;
}
In my class I've tried a few variations on like this:
//db = the databaseadapter
db.open();
long loadID = contactList.getSelectedItemId();
//contact list is a spinner that is auto populated with each new entry added to it.
Cursor cursor = db.getClient(loadID);
db.deleteClient(cursor);
db.close();
AND THIS
dh.getWritableDatabase();
long currentlySelected = contactList.getSelectedItemId();
dh.delete(currentlySelected);
dh.close();
One deletes but not the right selection - the other causes an immediate crash. DDMS has given hints but I cant figure out what else could be going on.
Any thoughts on this structure in general or better techniques on this approach?
Spinner loaded like this:
private void loadSpinnerData() {
// database handler
DatabaseHandler dbh = new DatabaseHandler(getApplicationContext());
// Spinner Drop down elements
List<String> lables = dbh.getAllLabels();
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, lables);
// Drop down layout style - list view with radio button
dataAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
contactList.setAdapter(dataAdapter);
}

Related

I cant delete some rows by id in SQLite

I always cant delete first two sometimes three records. They are on Listview, when you press element you will see delete button on another layout. On Log im getting correct index for every element.
So here is my code:
Main Activity:
viewOfT.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i=new Intent(MainActivity.this, popupWindow.class);
i.putExtra("index",id);
startActivity(i);
}
});
}
public void populateListView() {
Cursor data = db.getData();
ArrayList<String> listData = new ArrayList<>();
while(data.moveToNext()){
k.setId(data.getInt(0));
k.setTask(data.getString(1));
listData.add("- " + k.getTask());
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
listData);
viewOfT.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
viewOfT.invalidateViews();
Delete button in other activity:
del.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bundle bundle=getIntent().getExtras();
long value=bundle.getLong("index");
db.deleteRecord(value);
finish(); }
});
And SQLHelper:
public void deleteRecord(long id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + "=" + id, null);
close();
}
1) Delete populateListView method
2) Add the following as class variables:-
SimpleCursorAdpater sca;
Cursor data;
3) in the onCreate method add :-
data = getData();
sca = new SimpleCursorAdapter(
this, // Context same as for array adapter
android.R.layout.simple_list_item_1, // layout to be used
data, // <<<<<<<< the cursor to be used for the list
new String[]{"columnname_to_be_displayed"}, // <<<<<<<< cursor column to display name
new int[android.R.id.text1], // the view into which the cursor data will be placed
0 // a flag 0 is fine
);
viewOfT.setAdapter(arrayAdapter);
4) Add a new method to override the 'onResume' method (or alter it if already overridden) :-
#Override
protected void onResume() {
super.onResume();
data = getData();
sca.swapCursor(); // can you sca.notifyDatasetChanged()
}
As you are calling another activity to delete the task, onResume will be called when returning from the other activity so the data is again retrieved from the database (deleted row will not exist) and the adpater is told to refresh the data.
You should ideally also override the onDestroy() method to close the cursor (data.close();)
Important Consideration
A cursor column named _id must exist for CursorAdapters (that's how the SimpleCursorAdapter knows what pass to the onItemClickListener).
if KEY_ID does not equate to _id; you either need to change KEY_ID to _id or amend the getData() method to include the _id column (which should be the value of the row's identifier) e.g. assuming a very basic query:
public Cursor getData() {
return db.query(TABLE_NAME,"rowid AS _id, *",null,null,null,null,null);
} // Note! will add an extra column so beware if using column offsets
or perhaps :-
public Cursor getData() {
return db.query(TABLE_NAME,KEY_ID + " AS _id, *",null,null,null,null,null);
} // Note! will add an extra column so beware if using column offsets
A Note on Column offsets
In your code you have :-
k.setId(data.getInt(0));
k.setTask(data.getString(1));
0 and 1 are column offsets (and could change e.g. the two alternative getData() methods). As such it's generally better to take advantage of the Cursor method getColumnIndex(columnname) e.g. the above could be :-
k.setId(data.getInt(data.getColumnIndex(KEY_ID));
k.setTask(data.getString(data.getColumnIndex("TASK_COLUMN")));
Note! not that you will need to create an Array as the SimpleCursorAdpater takes the cursor as the source. (KEY_ID would likely have to be prefixed with the DatabaseHelper Class).

Adding texts into Textview from sqlite database with rowID

I've a list view which is populated by my database. Now in the OnItemClickListener I passed the row id to the next Activity. In that activity I have two text views and I want to add texts in those text views from the my database.
As a beginner I'm stuck here, What should I do now?
If the id(not the position of the item in the listviw) you are passing to the next activity is primary key or it is mapped somehow to your database table then you can simply query your database with a where clause to get the specific row from the table.
Another simple solution may be passing the data from the same activity to the another activity over the intent (if they are some small size), instead of making another query to the database tables.
Just pass in the row id to the database:
SqliteDatabase mySqlLiteDatabase;
View parentThis = (LinearLayout)inflater.inflate(R.layout.list_view);
lvDatabase = (ListView)parentThis.findViewById(R.id.listview);
lvDatabase.setAdapter(String[] list_Of_Items_From_Database);
lvDatabase.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
sql = "Select text from my_database where _id=" + id;
mySqlLiteDatabase.openDatabase(yourDatabasePath,null,SQLiteDatabase.OPEN_READWRITE);
Cursor c = mySqlLiteDatabase.rawquery(sql);
TextView textView = (TextView)parentThis.findViewById(R.id.mytextview);
if (c !=null) {
if (c.moveToFirst()) {
textView.setText(c.getString(c.getColumnIndex("Text")));
}
}
}
});
Hopefully your database table has an identity column in it (_id)
pass all the data in an array by quering into db and then display it in listView.
public ArrayList<String> getAllNumbers(){
ArrayList<String> labels = new ArrayList<String>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_CONTACTS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
String number=cursor.getString(1);
labels.add(number);
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
db.close();
// returning lables
return labels;
}
then fetch it on item click of listview and pass it to another activity.
#Override
public boolean onItemLongClick(AdapterView<?> parent,
final View view, final int position, long arg3) {
title = view.getTag(R.string.title).toString();
Intent intent_compose = new Intent(ActivityA.this,
ActivityB.class);
startActivity(intent_compose);
}

Getting Primary ID on clicking a List Item in Android

I am trying to create a list view for a password manger which will populate a listview with items from Database and when someone clicks it will return the primaryid.... I have seen other examples but not able to get it done corectly.... Here's what I have done so far.... I am able to Populate the List View but not able to handle on click events :(
ArrayList<String> listItems=new ArrayList<String>();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice , listItems);
SQLiteDatabase DB= null;
final String TableName = "XIBEAT_PASSWORDS";
String DBname="Xibeat_Crypto_Knight_Vault";
try {
DB = this.openOrCreateDatabase(DBname, MODE_PRIVATE, null);
DB.execSQL("CREATE TABLE IF NOT EXISTS " + TableName + " ('_id' INTEGER PRIMARY KEY AUTOINCREMENT,HOST TEXT, URL TEXT, PASSWORD TEXT, NOTES TEXT, TAG TEXT, TIME TEXT, DATE TEXT, EXPIRE TEXT, EDITED TEXT, STRENGTH TEXT, REASON TEXT);");
Cursor c = DB.rawQuery("SELECT * FROM " + TableName , null);
int host= c.getColumnIndex("HOST");
String title="";
c.moveToFirst();
if(c!=null)
{
while (c.moveToNext()){
title = c.getString(host);
//Toast(title);
listItems.add(title);
}
}
final ListView passList=(ListView)findViewById(R.id.passlist);
passList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listItems));
//===============ONCLICK LISTENER+=========
passList.setOnItemClickListener(new OnItemClickListener()
{public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
}});
} finally {
if (DB != null)
DB.close();
}
}
If you are reading data from a Cursor, you should be using a CursorAdapter or one of its subclassses such as SimpleCursorAdapter in place of ArrayAdapter:
Cursor c = DB.rawQuery("SELECT * FROM " + TableName , null);
final ListView passList=(ListView)findViewById(R.id.passlist);
passList.setAdapter(new SimpleCursorAdapter(this, // Context
android.R.layout.simple_list_item_1, // Layout
c, // Your Cursor
new String[] { "HOST" }, // Column(s) you want to display
new int[] { android.R.id.text1 }),
0); // Flags, 0 -> don't auto-requery when the data changes
The full signature for onItemClick is:
onItemClick(AdapterView parent, View view, int position, long id)
If you use a CursorAdapter, then the last parameter, id, is the _id column in your database.
Use a custom List adapter that saves the Id (getColumnIndex("_id");) in your custom object instead of having Android create the simple view for you.
It's not a good idea to use ArrayAdapter to load from DB. You should use CursorAdapter and CursorLoader to manage database instead. SimpleCursorAdapter is deprecated.
Here's a good tutorial on custom CursorAdapter: link
Another one for CursorLoaders: link

Add the contents of a database to a ListView via a Cursor

So I'm gunna try give as much information as I can to get this sorted. My application contains a database with the standard methods implemented; retrieving a record or all records returns a Cursor.
My application has a ListView, a text box and an add button. Here's what I'm trying to achieve (please note, the first is the most important):
I would like to display the current contents of the database in the ListView area.
I want to have the button insert whatever is in the text box into the database (and the ListView should automatically update to show the insertion)
I would like the ability to tap an item in the ListView and have it deleted from the database.
I have tried to tackle the first bullet point through assigning a Cursor to the return of the getAllRecords() method; Cursor c = dba.getAllRecords();. I have tired to get it to add field entries via a for-loop which didn't turn out too well.
Button add;
EditText tm;
ListView lv;
DBAdapter dba = new DBAdapter(this);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_general);
add = (Button) findViewById(R.id.button1);
tm = (EditText) findViewById(R.id.editText1);
lv = (ListView) findViewById(R.id.generalList);
Cursor c = dba.getAllRecords();
c.moveToFirst();
// Trying to add database contents to ListView here.
add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
insertIntoDatabase();
}
});
}
If you have a Cursor from a database and whant to show into a list, and is simple data like a few text values. Take a look at SimpleCursorAdapter.
The situation is this, you need an adapter, the adapter is the one that loads from the cursor and push into the layout that represent the correspoding list item. Anything that inherits from a CursorAdapter is good. All depends on how much flexibility you need, so you may implement as much as you need.
This is a snnipet from a sample app that I posted at github.
https://github.com/soynerdito/trainningSample/blob/master/src/com/example/sample/app/Dashboard.java
Also the app is in the marketplace. Is just a very simple app used during a "trainning" the app is called "Nerdito Sample" search for it, try and the code is on github. Adds items to a database and show in list.
Sample:
Device device = new Device();
Cursor cursor = mdb.get(device);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_2, cursor, new String[] {
device.mDescription.mName, device.mDeviceID.mName },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
// Create Cursor and set to List
mDeviceListView.setAdapter(adapter);

How to save cursor in activity?

I'm population my listView using Cursor, but when I navigate away from my activity and then return back my listview is empty. Here is my code:
#Override
public void onCreate(Bundle savedInstanceState) {
...
DBAdapter db = new DBAdapter(context);
db.open();
Cursor c = db.getAll();
db.close();
startManagingCursor(c);
String[] columns = new String[] { ... };
int[] to = new int[] { ... };
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, columns, to);
this.setListAdapter(mAdapter);
...
}
I've seen here questions about saving position of Cursor, but not the Cursor itself. Probably I just missing something, shall I save my cursor (how can I do it?) or it's better(faster, cheaper) to create new cursor every time using my DBadapter?
Thanks
startManagingCursor() makes your close() call unnecessary. As long as you didnt get exceptions about not finalizing or closing your cursor you have done anything right.

Categories

Resources