What's the purpose of item-id's in Android ListView Adapter?
There are probably many reasons to have stable item IDs. A default implementation cannot be given since it depends on the type of Object being stored in the Adapter.
Android has a check to make sure that item IDs are used only when they are stabled, i.e. the subclass has properly overridden getItemId
; BaseAdapter.hasStableIds must be overriden to return true.
Few reasons I have come across:
AdapterView.OnItemClickListener's method
onItemClick(AdapterView<?> parent, View view, int position, long id)
also sendslong id
the getCheckedItemIds method
The result is only valid if the choice mode has not been set to CHOICE_MODE_NONE and the adapter has stable IDs.
Reply to "Because have to implement that": you don't have to If you don't use the features, there's no need. But if you do, don't forget to override boolean hasStableIds()
as well.
Android - what is the meaning of StableIDs?
Stable IDs allow the ListView
to optimize for the case when items remain the same between notifyDataSetChanged
calls. The IDs it refers to are the ones returned from getItemId
.
Without it, the ListView
has to recreate all View
s since it can't know if the item IDs are the same between data changes (e.g. if the ID is just the index in the data, it has to recreate everything). With it, it can refrain from recreating View
s that kept their item IDs.
android-Get id of item in listView
Try to get id from Contact HashMap using list item position of Contact List instead of getting id from TextView text as below :
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), contactList.get(position).get("ID"), Toast.LENGTH_SHORT).show();
}
});
Android - ListView Items with specific IDs
Just follow these steps
Make a simple class having two variables like name and id class name: customer
now make a adapter class extending base adaptor override the getView method and set the text(name) of the customer
Handle clicks in the in listview onitemclick method
So heres a sample code
Pass the adapter an
ArrayList<Customer>
So now your listview will have customer objects
On click you will get the customer object,use the parent.itematposition(position)
Cast the result of this method into customer alike this
Customer c=(Customer)parent.itematposition(position);
System.out.print(c.getId+c.getName());
public class Customer{
private Sting name;
private String id;
Provide setters and getters for both them so that they can be used above
}
Difference between RowId and Position in onItemLongClick's parameter
position
is the clicked element's position in your Adapter (so you can do adapter.getItem(position)
)
row id
is the id that corresponds to that element, what your Adapter returns in the getItemId()
method.
Attaching ID data to listview items
Theoretically you could do either approaches and it will probably work without problems. In the long run however, I would say you'll be better of with a simple entity object and a custom adapter. More specifically, from the looks of it, I would opt for an ArrayAdapter, and you already seem to be using some sort of simple entity object for the array ann
.
There are tons of examples that can show you how to extend ArrayAdapter. The most important part however is the getView()
method, which in it's most basic form could look somewhat like this:
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if (null == convertView) {
row = mInflater.inflate(R.layout.list_item, null);
} else {
row = convertView;
}
MyObject item = (MyObject) getItem(position);
TextView tv = (TextView) row.findViewById(android.R.id.xxx);
tv.setText(item.getTitle);
// same for other fields/views; e.g. author, date etc
return row;
}
In stead of creating a SimpleAdapter, now create an instance of your CustomAdapter, pass it your array (or list) of entity objects, and set the whole as adapter to your list:
MyObject[] objects = ...
setListAdapter(new ArrayAdapter<string>(this, R.layout.list_item, objects));
Since you're now dealing with the objects directly, in stead of first creating a bunch of strings representation out of the different fields, you can also easily access the 'id' of every item. Even better, you can add a whole lot of different fields without worrying how it will look like in the list, since the visual representation is determined by what you set (and don't set) in the getView()
method of your adapter.
Assigning ID to a Row in an Android ListView
Here's how I solved the problem. I got the employee_ids and employee_names from the local SQLite Database, then I created an ArrayList of employeeNamesArray and an ArrayList of employeeIdArray at the same time. Thus, the employeeIdArray[0] would match with employeeNameArray[0], employeeIdArray[1] would match with employeeNameArray[1], etc.
Once the ArrayLists were created, I fed employeeNameArray into the ListView.
Later, in onListItemClick, I retreive the position of the selected ListView row. This 'position' will corrospond to the position in the ArrayLists - thus, if I select the first row in the ListView, the position will be zero, and employeeNameArray[0] matches with employeeIdArray[0]. I grab the coroloating entry from employeeIdArray and push that to the next Activity by using putExtra.
public class MyFirstDatabase extends ListActivity {
ArrayList<String> employeeIdArray = new ArrayList<String>(); // List of EmployeeIDs
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Open the database
SQLiteDatabase db;
db = openOrCreateDatabase("mydb.db",SQLiteDatabase.CREATE_IF_NECESSARY, null);
db.setVersion(1);
db.setLocale(Locale.getDefault());
db.setLockingEnabled(true);
// Query the database
Cursor cur = db.query("employee", null, null, null, null, null, "employee_lastname");
cur.moveToFirst(); // move to the begin of the db results
ArrayList<String> employeeNameArray = new ArrayList<String>(); // Initialize mArrayList
while (cur.isAfterLast() == false) {
employeeNameArray.add(cur.getString(1)); // add the employee name to the nameArray
employeeIdArray.add(cur.getString(0)); // add the employee id to the idArray
cur.moveToNext(); // move to the next result set in the cursor
}
cur.close(); // close the cursor
// put the nameArray into the ListView
setListAdapter(new ArrayAdapter<String>(this,R.layout.list_item,employeeNameArray));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
}
protected void onListItemClick(ListView l, View v, final int position, long id) {
super.onListItemClick(l, v, position, id);
Intent myIntent = new Intent(this, SubView.class); // when a row is tapped, load SubView.class
Integer selectionID = Integer.parseInt(employeeIdArray.get(position)); // get the value from employeIdArray which corrosponds to the 'position' of the selected row
myIntent.putExtra("RowID", selectionID); // add selectionID to the Intent
startActivityForResult(myIntent, 0); // display SubView.class
}
}
What does AdapterView? mean in the OnitemClick() Method? What is the use of other parameters in it?
The <?>
indicates a Generic. Read more about them here.
Here is what the documentation says about the parameters:
onItemClick(AdapterView<?> parent, View view, int position, long id)
parent The AdapterView where the click happened.
view The view within the AdapterView that was clicked (this will be a view provided by the adapter)
position The position of the view in the adapter.
id The row id of the item that was clicked.
The AdapterView
could be a ListView
, GridView
, Spinner
, etc. The question mark inside the angle brackets indicates that it could be any of them. This is called generics in Java. You can use parent in code to do something to the whole view. For example, if you were using a ListView
you could hide the whole ListView
by the following line of code:
parent.setVisibility(View.GONE);
The View
refers to a specific item within the AdapterView
. In a ListView
it is the row. Thus, you can get a reference to a TextView
within a row by saying something like this:
TextView myTextView = (TextView) view.findViewById(R.id.textView1);
String text = myTextView.getText().toString();
The position is the position of the view in the parent. For a ListView
, it is the row number. The top row is position 0, the second row is position 1, the third row is position 2, etc. Note that if your ListView
has a header view (like if you did ListView.addHeaderView(View)
) then the header view would be position 0 and the actual rows would start their numbering at 1.
Sometimes id is the same as position and sometimes it is different. If you are using an ArrayAdapter
or SimpleAdapter
then they are the same (except in the case that there is a header view and then they are off by one). For a CursorAdapter
(and consequently a SimpleCursorAdapter
) the id returns the row id of the table, that is, _id
.
Here are a few other good answers on this topic:
- https://stackoverflow.com/a/9863279/3681880
- https://stackoverflow.com/a/12966006/3681880
- https://stackoverflow.com/a/24531354/3681880
Related Topics
Set Loadurltimeoutvalue on Webview
Can Not Set Debuggable Flag in Androidmanifest.Xml
Firebase Sort by Points Depending on Date
How to Add Code Obfuscation for My Android Application
Android Java.Util.Concurrent.Timeunit Convert Milliseconds to Minutes
What Does the Filter Parameter to Createscaledbitmap Do
Existing 3-Function Callback to Kotlin Coroutines
Android - Wake Up and Unlock Device
How Are Android Activities Handled with Jetpack Compose and Compose Navigation
Single Click and Double Click of a Button in Android
Broadcast Receiver Not Working in Ics If the App Is Not Started Atleast Once
How to Show Daily Offline Notifications in Android 10
How to Handle One-Shot Operations in Jetpack Compose
Differencebetween Sendstickybroadcast and Sendbroadcast in Android