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);
}
Related
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).
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);
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
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);
}
I'm working on an app that allows the user to create notes while rehearsing a play. The user can view the notes they have created in a listview, and edit and delete them if they wish.
Take for example the user creates 3 notes. In the database, the row_id's will be 1, 2 and 3. So when the user views the notes in the listview, they will also be in the order 1, 2, 3 (intially 0, 1, 2 before I increment the values). So the user can view and delete the correct row from the database.
The problem arises when the user decides to delete a note. Say the user deletes the note in position 2. Thus our database will have row_id's 1 and 3. But in the listview, they will be in the position 1 and 2. So if the user clicks on the note in position 2 in the listview it should return the row in the database with row_id 3. However it tries to look for the row_id 2 which doesn't exist, and hence crashes.
I need to know how to obtain the corresponding row_id, given the user's selection in the listview. Here is the code below that does this:
// When the user selects "Delete" in context menu
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
.getMenuInfo();
switch (item.getItemId()) {
case DELETE_ID:
deleteNote(info.id + 1);
return true;
}
return super.onContextItemSelected(item);
}
// This method actually deletes the selected note
private void deleteNote(long id) {
Log.d(TAG, "Deleting row: " + id);
mNDbAdapter.deleteNote(id);
mCursor = mNDbAdapter.fetchAllNotes();
startManagingCursor(mCursor);
fillData();
// TODO: Update play database if there are no notes left for a line.
}
// When the user clicks on an item, display the selected note
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
viewNote(id, "", "", true);
}
// This is where we display the note in a custom alert dialog. I've ommited
// the rest of the code in this method because the problem lies in this line:
// "mCursor = mNDbAdapter.fetchNote(newId);"
// I need to replace "newId" with the row_id in the database.
private void viewNote(long id, String defaultTitle, String defaultNote,
boolean fresh) {
final int lineNumber;
String title;
String note;
id++;
final long newId = id;
Log.d(TAG, "Returning row: " + newId);
mCursor = mNDbAdapter.fetchNote(newId);
lineNumber = (mCursor.getInt(mCursor.getColumnIndex("number")));
title = (mCursor.getString(mCursor.getColumnIndex("title")));
note = (mCursor.getString(mCursor.getColumnIndex("note")));
.
.
.
}
Let me know if you would like me to show anymore code. It seems like something so simple but I just can't find a solution.
Thanks!
EDIT
I fixed the problem. I answered the question below.
Okay I fixed the problem (temporarily at least).
The problem was I was using my own adapter class I created. It was not keeping track of which item in the list corresponded with the item in the database. I have now rewritten the "fillData()" method using a SimpleCursorAdapter.
This is the OLD implementation, with my own custom adapter:
private void fillData() {
String note;
notes = new ArrayList<String>();
// Populate arraylist with database data
if (mCursor.moveToFirst()) {
do {
// Get current row's character and line
note = mCursor.getString(mCursor.getColumnIndex("title"));
Log.d(TAG, "Adding note: " + note);
notes.add(note);
} while (mCursor.moveToNext());
}
// Fill list with our custom adapter
NoteAdapter adapter = new NoteAdapter(this, R.layout.note_row_layout,
notes);
setListAdapter(adapter);
}
and this is the same class rewitten with a SimpleCursorAdapter:
private void fillData() {
mFrom = new String[] { NoteDbAdapter.KEY_TITLE };
mTo = new int[] { R.id.textNote };
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.note_row_layout, mCursor, mFrom, mTo);
setListAdapter(adapter);
}
The reason I created my own adapter class was because I also had a checkbox in each row of the list (for multi-delete).
My question now is, am I able to obtain the state of each checkbox (whether its checked or not) when the user decides to do a multiple delete when using a SimpleCursorAdapter?
Thanks.