Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ListView tips and tricks

Avatar for Tibi Giurgiu Tibi Giurgiu
September 13, 2012

ListView tips and tricks

Avatar for Tibi Giurgiu

Tibi Giurgiu

September 13, 2012
Tweet

Other Decks in Programming

Transcript

  1. Overview • a view group that displays a list of

    scrollable items • designed for scalability and performance • an Adapter pulls content from a source and converts each item result into a view that's placed into the list. java.lang.Object ↳ android.view.View ↳ android.view.ViewGroup ↳ android.widget.AdapterView<T extends android.widget.Adapter> ↳ android.widget.AbsListView ↳ android.widget.ListView
  2. Virtualization • Problem: large data sets – Memory – Performance

    • Solution – Populate on demand – Recycle views to reduce object churn
  3. • DOs – use the recycled view – ok to

    use drawable resources (cached internally) • DON'Ts – perform long operations (network, db, sharedPrefs, files, bitmaps etc.) – call findViewById() if not necessary => ViewHolder pattern – change convertView structure (use view type system for this instead) getView()
  4. Multiple Item Types • int getItemViewType(int position) – type of

    View for a given position – used to provide the right convertView • getViewTypeCount() – how many types to expect – must remain constant
  5. Handling dataset changes • notifyDataSetChanged() – new or updated data

    – list view rescans the adapter for the views on screen – MUST be called everytime you change your adapter – commit adapter changes on the UI thread, call notifyDataSetChanged() in the same UI event • notifyDataSetInvalidated() – no more data available
  6. Handling emptiness • AdapterView.setEmptyView(View emptyView) – AdapterView hides/displays it according

    to the adapter state – the AdapterView and the empty view are mutually exclusive in term of visibility • ListActivity/ListFragment makes it easier – id for the ListView: android.R.id.list – id for the empty view: android.R.id.empty
  7. Transcript and stack from bottom • android:transcriptMode – behavior of

    the list when the content changes – “disabled”, doesn’t scroll – “normal”, scrolls to the bottom if last item is visible – “alwaysScroll”, always scrolls to the bottom • android:stackFromBottom – stack items in reverse order – starts with the last item from the adapter
  8. Headers and Footers • ListView.addHeaderView() • ListView.addFooterView() • Must be

    called before setAdapter() • list.getAdapter() returns a android.widget.HeaderViewListAdapter
  9. Don't: android:layout_height="wrap_content" • getView() called too many times • forces

    ListView to measure a few children at layout time, to know how big it should be • Solution: – android:layout_height="fill_parent" :) – inside LinearLayout, android:layout_height="0dp" and use layout_weight
  10. Add clickable areas • ListView blocks clicks of itemview containing

    at least one focusable descendant – Solution: • android:focusable="false" on all controls • set android:descendantFocusability="blocksDescendants" for the root • Android, by default, recursively dispatches the pressed state of a ViewGroup to all of its children – Solution: don’t ‘accept’ the pressed state when the parent is already in the pressed state.
  11. Lazy loading images • the view you’re loading the image

    for might be recycled before the async operation finishes • attach some piece of information to the view that identifies which row is associated with it
  12. private static class ThumbnailTask extends AsyncTask<Void, Void, Bitmap> { private

    int mPosition; private ViewHolder mHolder; public ThumbnailTask(int position, ViewHolder holder) { mPosition = position; mHolder = holder; } @Override protected Bitmap doInBackground(Void... arg0) { // Download bitmap here } @Override protected void onPostExecute(Bitmap bitmap) { if (mHolder.position == mPosition) { mHolder.thumbnail.setImageBitmap(bitmap); } } }
  13. public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState ==

    OnScrollListener.SCROLL_STATE_FLING) { mPhotoLoader.pause(); } else if (mDisplayPhotos) { mPhotoLoader.resume(); } } • start an asynchronous operation on every getView() call while scrolling => most of the results would be discarded • setOnScrollListener(), don't load if SCROLL_STATE_FLING
  14. Clasic Lazy loading pattern public View getView(int position, View convertView,

    ViewGroup parent) { // ... setupView Bitmap image = loadImageFromCache(url); if (image != null) { imageView.setImageBitmap(image); } else { AsyncTask loadImageTask = new AsyncTask<Void, Void, Bitmap>() { protected Bitmap doInBackground(Void... params) { return loadImageFromNetwork(url); } protected void onPostExecute(Bitmap image) { if (image != null && imageView.getTag().equals(url)) { imageView.setImageBitmap(image); } } }; // ... setup no image loaded view imageView.setTag(url); loadImageTask.execute(); } }
  15. Better solution public View getView(int position, View convertView, ViewGroup parent)

    { // ... setupView Bitmap image = loadImageFromCache(url); if (image != null) { imageView.setImageBitmap(image); } else { AsyncTask loadImageTask = new AsyncTask<Void, Void, Bitmap>() { protected Bitmap doInBackground(Void... params) { return loadImageFromNetwork(url); } protected void onPostExecute(Bitmap image) { if (image != null && imageView.getTag().equals(url)) { adapter.notifyDataSetChanged(); } } }; // ... setup no image loaded view imageView.setTag(url); loadImageTask.execute(); } }
  16. • Android Developers https://developer.android.com/guide/topics/ui/layout/listview.html • Google IO 10, The world

    of ListView http://www.google.com/events/io/2010/sessions/world-of-listview-android.html • Cyril Motier, Android Dev Blog http://android.cyrilmottier.com • Lucas Rocha, Performance Tips for Android’s ListView http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ • Janusz Leidgens, Lazy Loading in Lists http://journeyman.janusz.de/ References