Getting Primary ID on clicking a List Item in Android - java

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

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

How to delete items from listview created from SQLite using OnItemLongClickListener()?

I can't find an answer to delete in a listview created using SimpleCursorAdapter
So i make this listview in a fragment, here's the code
final Cursor cursor = myDb.cautarevenituri();
// The desired columns to be bound
final String[] columns = new String[] {
DatabaseHelper.COL_2,
DatabaseHelper.COL_3
};
int[] toviewids = new int[] { R.id.nume_item,R.id.valoare_item};
dataAdapter = new SimpleCursorAdapter(getActivity().getBaseContext(),R.layout.item_layout,cursor,columns,toviewids,0);
//
final ListView listView = (ListView)getView().findViewById(R.id.listView_venituri);
listView.setAdapter(dataAdapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long arg3) {
Toast.makeText(getActivity(), " " + position, Toast.LENGTH_LONG).show();
//delete from listview in database and listview too??
//
//
return false;
}
});
Thank you.
Delete from Database and refresh the listview.
You have to update your list that you passed into the adapter and then call adapter.notifyDataSetChanged()
Use the swapCursor() method to update the data inside a SimpleCursorAdapter:
myDb.getWriteableDatabase().delete(TABLE_NAME, KEY_ID + "=?", position);
Cursor newCursor = myDb.getReadableDatabase().query(**etc.**);
dataAdapter.swapCursor(newCursor);

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

Android - Deleting database entries using cursor

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

Custom SimpleCursorAdapter with imageButton random values

I am trying to add image button to my custom SimpleCursorAdapter for my ListView in my project but I have got one problem with repeating and totally random value of one field.
This is a code of it:
public class MyCursorAdapter extends SimpleCursorAdapter {
public MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
super.bindView(view, context, cursor);
final Context t = context;
final Cursor c = cursor;
ImageButton delimageButton = (ImageButton)view.findViewById(R.id.deletebutton);
delimageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(t,
"Delete ID: " + c.getInt(c.getColumnIndex(MyDBAdapter.KEY_ID)), Toast.LENGTH_SHORT).show();
}
});
if(cursor.getLong(cursor.getColumnIndex(MyDBAdapter.KEY_OWNID))>0)
{
TextView own = (TextView)view.findViewById(R.id.ownInfo);
own.setText("OWN");
}
else
{
TextView own = (TextView)view.findViewById(R.id.ownInfo);
own.setText("");
}
}
}
Now, when I press delimageButton what I get is some random ID of one record (row) of ListView that is in current view (I can see it, but it is not the correct id) e.g. if you can see like 5 rows on screen and you press on one of buttons you will get id of other row (one of those 5) but not this one which you pressed (in most of the cases). I remember that there was some trick with this own TextView, but I don't see how it can be putted in here.
So, can you please advice me how can I make it to show correct ID?
I'll be glad for help.
EDIT
There is a whole code responsible for setting a ListView together with calling MyCursorAdapter:
private void refreshList() {
mySQLiteAdapter = new MyDBAdapter(this);
mySQLiteAdapter.open();
String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_GENRE,
MyDBAdapter.KEY_OWNID, MyDBAdapter.KEY_ID };
Cursor contentRead = mySQLiteAdapter.getAllEntries(false, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null);
startManagingCursor(contentRead);
Log.d(TAG, Integer.toString(contentRead.getCount()));
MyCursorAdapter adapterCursor = new MyCursorAdapter(this,
R.layout.my_row, contentRead, columns, new int[] {
R.id.rowTitle, R.id.detail });
this.setListAdapter(adapterCursor);
mySQLiteAdapter.close();
}
To clarify, the activity is ListActivity.
Your OnClickListener is getting the id from the cursor when it is clicked, not when it is constructed. Meanwhile, the listview is changing the cursor position as you scroll around.
I think if you look carefully, you'll find the Toast is displaying the id of the last item that was loaded into view rather than the item that contains the button you clicked.
You can solve this by getting the id when you construct the click listener, like this:
delimageButton.setOnClickListener(new OnClickListener() {
private int id = c.getInt(c.getColumnIndex(MyDBAdapter.KEY_ID));
#Override
public void onClick(View arg0) {
Toast.makeText(t,
"Delete ID: " + id, Toast.LENGTH_SHORT).show();
}
});

Categories

Resources