I display the user data from SQLite database using a custom CursorAdapter.
Each ListView item is actually a layout with many TextViews.
in the CursorAdapter.bindView() method I get database data from the Cursor, and display their modified, prettier versions to the user. Here's what I mean:
public void bindView(View view, Context context, Cursor cursor) {
//get listview items Views
TextView dayTextView = (TextView)view.findViewById(R.id.listview_item_day);
//...
//get data from cursor
int day = cursor.getInt(1);
//...
//display data nicely to the user
String sDay = "Day number " + String.valueOf(day) " was a very nice day";
dayTextView.setText(sDay);
}
I want that when the user long clicks an item (I'll use OnItemLongClickListener for that), the item will be deleted (easy peasy) but I also want to delete the day record from the database.
When the ListView item gets clicked, I have the next parameters supplied to me (in OnItemLongClickListener):
AdapterView<?> adapterView, View view, int position, long id
How do I get to the database record from all these parameters? I could use TextView.getText() and apply some string manipulation methods to the result (remember I added strings to the data before setting it in ListView), but I feel like there's another, more clever way.
You might use a List<Integer> days = new Arraylist<>(); to keep days you are modifying and so the index of the list alway will be same as position and you can get your day content by days.get(position) and get item from your database.
you should define your list out of bindView
Related
I've done a list that shows titles, when i click on an item is opened an activity that shows the description of the element; i'm getting this description using the id of the element.
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String descrizione=mydb.getDescription(id+1,titolo.getText().toString());
}
This is the method in my database:
public String getDescription(long id,String formulario)
{
String descrizione="NADA";
SQLiteDatabase db= this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from "+formulario+" where id="+id+"", null );
if(res!=null && res.getCount()>0){
res.moveToFirst();
descrizione = res.getString(res.getColumnIndex("Descrizione"));
res.close();
}
return descrizione;
}
THE PROBLEM: when i delete an element all the description result shifted forward. I don't know if the problem is with the cursor, the item's id acquisition or with the delete method... any help is valued
This is my delete method:
public Integer deleteFormula (String formula, String formulario)
{
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(formulario, "Formule = ? ", new String[] { formula});
}
First off, when you want to show database data in a ListView, you should use CursorAdapter to bind database data with your ListView. From the code you've posted, can't tell whether and how it's been implemented. If you have any doubts about it I suggest you look into this article which explains this subject very well https://github.com/codepath/android_guides/wiki/Populating-a-ListView-with-a-CursorAdapter
Secondly, when you successfully bind the data to your ListView, then in onItemClick method you can use the second parameter which is View and represents the clicked ListView row , to retrieve the data that is shown in that row.
Thirdly, when you delete a row from your database table, you should synchronize your ListView by getting a new cursor and calling your CursorAdapter changeCursor method with new cursor as argument.
This is just a rough sketch, but I hope it will help at least a little bit.
Cursor adapter would be the optimal solution. But if you want to stick with the same code when you delete a row from your database table you must ensure that you also get the updated list of data from your database.
And also you don't have to add + 1 to this code. If you have to add + 1 it means you're doing things wrong.
String descrizione=mydb.getDescription(id+1,titolo.getText().toString());
This would work well if you are just constantly updating your list with the data from your database whenever there are changes, and id doesn't represent the databaseID as it represents the ID of the view within the adapter.
Your issue is using position to determine id in :-
String descrizione=mydb.getDescription(id+1,titolo.getText().toString());
At first, assuming 3 columns inserted:-
First column has an id of 1, 2nd 2 and 3rd 3. So initially if rows are sorted according to id (good chance of this happening but no guarantee) then position 0 (first row displayed) + 1, will display data for id 1, position (2nd item in the List) 1 will show data for id 2 etc and all looks good.
However if you delete id 2 then:-
The 1st item in the list will display data from id 1 and position 0 still equates to id 1.
However the 2nd Item in the list will display data from the table for row id 3 BUT position 1 + 1 = 2 so the wrong id is calculated.
In short you cannot use position to correlate to the id.
You need to somehow get the appropriate row. Perhaps the easiest solution is to use a CursorAdapater, then id will be the id (column name must be _id).
After going through many posts I am posting my query. Not able to get proper resolution for my problem.
I am using sqlite and inserting some data (name, info etc..)
Now I get the all rows and show in list view.
Now user selects a one list entry for deletion, I have to call db.delete with id which is rowid of that particular record.
How will get the record id?
When user selects from list view I have position number which is index to the list. But not the database row id where that entry resides.
Do i have to save all ids returned when I call db.insert(table, data) when rows are created?
all examples show the implementation like
public void deleteRow(long id) {
db.delete(TABLE_NAME,KEY_ID + " = ?",
new String[] { String.valueOf(id) });
}
where should i get id from?
For setup a list view you have create an Adapter, right?
The adapter hold your entries and create the views.
Ask your adapter which item is on position x.
The BaseAdapter implement a getItemId method.
public long getItemId(int position) {
// Example for List<Object>
return mItems.get(position).getId();
}
You can simple call adapter.getItemId(x); or use OnItemClickListener that give the ID.
For more informations loot at the android developer pages.
SimpleAdapter:
http://developer.android.com/reference/android/widget/SimpleAdapter.html
ArrayAdapter:
http://developer.android.com/reference/android/widget/ArrayAdapter.html
BaseAdapter:
http://developer.android.com/reference/android/widget/BaseAdapter.html
I hope it helps.
Updated:
Use getItemId(int) instead of getItem(int), thanks to #pskink
I am learning how to create a spinner that loads dropdown from SQLite. I have an UI that consists of a spinner and a table. If user clicks spinner, the table's content will load according to the database based on the selected ID on spinner. If name not selected, it will load all contents in table.. However I can't find the way how to make the table reload based on the ID / name selected on spinner. Anyone can guide me?
The table itself is a joined table, which has following structure:
Table A : ID_Person | Name | Age
Table B : ID_Account | ID_Person | Amount
Spinner shows Person's name. Meanwhile the table will show the following structure:
Name | Age | Amount
My code for spinner:
public List<String> getAllDealers()
{
List<String> contentdealer = new ArrayList<String>();
// Select All Query
String selectQuery = "SELECT * FROM " +Dealer_TABLE;
cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
contentdealer.add(cursor.getString(1));
} while (cursor.moveToNext());
}
// closing connection
return contentdealer;
}
Here is how I build my Table for looping:
Cursor c = in.getViewInfo(); //method in db consists of query that i want table show
int rows = c.getCount();
int cols = c.getColumnCount();
c.moveToFirst();
// outer for loop
for (int i = 0; i < rows; i++)
{
//looping all rows based .getCount()
//looping all columns
for (int j = 0; j < cols; j++)
{
}
}
in.close();
See a similar but not exact same answer here
https://stackoverflow.com/a/11920785/1116836
I believe what you want is
spinner.setOnItemSelectedListener(new OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id)
{
Toast.makeText(context, "item selected, load some sql", Toast.LENGTH_LONG).show();
// position should match the index of the array in the items list you used for which item is selected, or here you could do
String selected = spinner.getSelectedItem().toString();
// or
String anotherway = spinner.getItemAtPosition(position).toString();
if (selected.equals("what ever the option was")) {
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView)
{
Toast.makeText(context, "nothing selected, load some sql", Toast.LENGTH_LONG).show();
}
});
likely to be able to select nothing, you will have to insert a view with no text, and allow that to be selected.
onNothinSelected is more for when a list is modified, or the currently selected item becomes unselected, e.g. when it is in in between selections it may call this method.
Callback method to be invoked when the selection disappears from this
view. The selection can disappear for instance when touch is activated
or when the adapter becomes empty.
So basically, when a new item is selected, call a method that loads some sql rows, clear your table and then display the new data.
EDIT: for comment
What you are trying to do is an event drive function. When someone selects a new option in the spinner, it is an event. You listen for this event by, as I showed above, implementing the OnItemSelectedListener().
One you implement this, you can find out what item is selected, as soon as it happens. Once a new item is selected, you need to determine what that item means you should do.
Once you have figured that out, run your SQL statement and query your database, load the data, set it in the adapter and then the user will see it.
If you are using a ListView, which you should be, then you need to clear the adapter to the ListView, and then add the new items.
You need to research ArrayAdapter, BaseAdapter, ViewHolder pattern, and ListView's.
A quick google search will have you up and running in no time.
When I grab info from a database (I am using MySQL), I'd like to also grab the id of the row and somehow assign it to each row of the 'listView`.
For example, let's say there is a table called fruit. fruit_id of 16 is orange. When the listView displays the list of fruit, and user clicks on a row that shows orange, i'd like to be able to access the fruit_id(16) of that row. But I'm not sure where to "hide" it.
Doing some initial research it seems there are multiple ways one can do this. The simplest might be something with using a tag, is this the best way? if so, how can you assign an id to it?
Create a class named Fruit.
class Fruit {
private int fruit_id;
private String fruit_name;
// Constructors
// Getters and Setters
}
Use an ArrayAdapter<Fruit> as the ListAdapter for your ListView. Then at ListView's onItemClickListener, get the Fruit object and get its id.
If you're using an ArrayAdapter to back your ListView, then #jaibatrik's suggestion is definitely a good one. However, if you're using a CursorAdapter, it's probably easier to exploit the return value of getItemId().
By default, a CursorAdapter will look for a column with the name "_id" in the Cursor you supply it and return that as id value whenever you click an item:
onItemClick(AdapterView<?> parent, View view, int position, long id)
That last value will contain the id of your cursor item. You can also override this behaviour and have it return any other unique value you may have access to in the Cursor.
The same is also true for an ArrayAdapter: by default it will return the position of the item in the array as unique id. However, you could easily make it return fruit_id for every item by overriding that method. Then it'll be passed in the onItemClick(...) directly, which saves you retrieving it (again) in there.
My questions is, if I grab, for example, item_id (not just item),
where do I put item_id in the listView rows (on Android side)?
The beauty of having objects that represent the data you're visualising in the list, is that you already have all the ingredients to make it work. Let's take the Fruit example given by #jaibatrik and add one getter for the sake of this example:
class Fruit {
private int fruit_id;
private String fruit_name;
// Constructors
// Getters and Setters
public int getId() { return fruit_id; }
}
In the comments you're describing you retrieve the fruit data from the database and populate it in a list:
List<Fruit> fruits = ...
That list should be the dataset backing your ArrayAdapter. To be more specific, since it's a typed class, you should have an ArrayAdapter<Fruit> instance that you set as adapter to the ListView.
Now, assuming you have an OnItemClickListener set against the ListView, it will fire whenever the user taps on an item. Using the parameters passed into the callback, you can retrieve the item that is associated with the position that was selected:
#Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = (Fruit) parent.getItemAtPosition(position);
int fruit_id = fruit.getId();
...
}
With the object retrieved, you can do anything you like with the data it holds. No need to explicitly set the id against the row views, since it should already be part of the dataset that backs the ListView.
I have a ListView in a ListActivity populated by a database table. Each row of the ListView is a RelativeLayout with three TextViews named rowid, date, and name in that order. I am able to select individual rows programmatically using the .setSelection(int position) method of the ListView.
Here is what I'm trying to do: When I push a button on the interface, get the rowid from the currently selected list row, and perform a db query using the rowid. I can't figure out how to get the rowid from the list itself. rowid may not be the same as the ID or position on the list as it is the rowid in the database.
I suspect this will require working with an adapter, but I've been trying/searching the web for a week and haven't been able to figure this out. Thanks for the help anyone can provide.
You know the list position of the currently selected item, you have a button outside the ListView that should trigger some action on that item, and you're not just making the ListView rows (or some child view within each row) clickable. Right?
You can get information from the list's adapter. getItem(int position) returns the object that is represented by the list item at position, so you can retrieve the information you need directly if it's stored in the object. getView(int position) returns the view for the row, allowing you to use findViewById(int id) to retrieve your TextView.
If you don't already have the adapter, you can get it from the ListView using getAdapter().
// ListView myListView = the ListView in question
// int selectedRow = the currently selected row in the ListView
// Each row in the ListView is backed by an object of type MyCustomDataClass
int dbRowId;
Adapter adapter = myListView.getAdapter();
MyCustomDataClass data = (MyCustomDataClass) adapter.getItem(selectedRow);
dbRowId = data.getDatabaseRowId();
// OR
dbRowId = data.rowId;
// OR whatever method the object has for getting the ID.
// OR
View listViewRow = adapter.getView(selectedRow);
TextView dbRowView = (TextView) listViewRow.findViewById(R.id.rowid);
String dbRowAsString = dbRowView.getText().toString();
dbRowId = Integer.parseInt(dbRowAsString);
You might also consider whether it would be more natural for the user to just tap the ListView row, rather than selecting the row and then pressing another button. Reno's answer might work better.
I ended up using the last method with the following code.
int dbRowId;
Adapter adapter = myListView.getAdapter();
View listViewRow = adapter.getView(selectedRow);
TextView dbRowView = (TextView) listViewRow.findViewById(R.id.rowid, null, null);
String dbRowAsString = dbRowView.getText().toString();
dbRowId = Integer.parseInt(dbRowAsString);
The only change I had to make was adding null, null to the parameters in .findViewByID
TextView dbRowView = (TextView) listViewRow.findViewById(R.id.rowid, null, null);