SlideShare a Scribd company logo
Dinosaurs and Androids:The
ListView evolution
Jorge J. Barroso / Fernando Cejas
Tech Lead Android Core / Android Developer
jbarroso@tuenti.com / fcejas@tuenti.com
@flipper83 / @fernando_cejas / @TuentiEng

Code samples:
https://github.com/android10/Inside_Android_ListView
Sunday, November 10, 13
Sunday, November 10, 13
1

Morphology

Component or Layout?
Sunday, November 10, 13
public abstract class AbsListView
extends AdapterView<ListAdapter>
public abstract class AdapterView
<T extends Adapter> extends
ViewGroup

Sunday, November 10, 13
ScrapViews
view

ListView

Sunday, November 10, 13

view

view

Adapter
/**
* Obtain the view and add it to our list of children. The view can be made
* fresh, converted from an unused view, or used as is if it was in the
* recycle bin.
*
* @param position Logical position in the list
* @param y Top or bottom edge of the view to add
* @param flow If flow is true, align top edge to y. If false, align bottom
*
edge to y.
* @param childrenLeft Left edge where children should be positioned
* @param selected Is this position selected?
* @return View that was added
*/
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected) {
View child;
if (!mDataChanged) {
// Try to use an existing view for this position
child = mRecycler.getActiveView(position);
if (child != null) {
// Found it -- we're using an existing child
// This just needs to be positioned
setupChild(child, position, y, flow, childrenLeft, selected, true);
return child;
}
}
// Make a new view for this position, or convert an unused view if possible
child = obtainView(position, mIsScrap);
// This needs to be positioned and measured
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
return child;
}

Sunday, November 10, 13

ListView
/**
* Get a view and have it show the data associated with the specified
* position. This is called when we have already discovered that the view is
* not available for reuse in the recycle bin. The only choices left are
* converting an old view or making a new one.
*
* @param position The position to display
* @param isScrap Array of at least 1 boolean, the first entry will become true if
*
the returned view was taken from the scrap heap, false if otherwise.
*
* @return A view displaying the data associated with the specified position
*/
View obtainView(int position, boolean[] isScrap) {
isScrap[0] = false;
View scrapView;
scrapView = mRecycler.getTransientStateView(position);
if (scrapView != null) {
return scrapView;
}
scrapView = mRecycler.getScrapView(position);
View child;
if (scrapView != null) {
child = mAdapter.getView(position, scrapView, this);
...
}

Sunday, November 10, 13

AbsListView
Sunday, November 10, 13
Demo
http://www.flickr.com/photos/farahmandnia/
Sunday, November 10, 13
2

ViewHolders

Is this really necessary?
http://www.flickr.com/photos/rojam/
Sunday, November 10, 13
Your code might call findViewById() frequently during the
scrolling of ListView, which can slow down performance. Even
when the Adapter returns an inflated view for recycling, you
still need to look up the elements and update them. A way
around repeated use of findViewById() is to use the "view
holder" design pattern.

Sunday, November 10, 13
@Override
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return v;
}
}
}
return null;
}

ViewGroup
Sunday, November 10, 13
Demo
http://www.flickr.com/photos/farahmandnia/
Sunday, November 10, 13
3

Optimization

Where are we wasting time?
http://www.flickr.com/photos/kabacchi/
Sunday, November 10, 13
ew
i
tV
e
G
Adapter

View

LruCache
<Bitmap>
Bitmap

Sunday, November 10, 13
Demo
http://www.flickr.com/photos/farahmandnia/
Sunday, November 10, 13
WHY
DOESN’T
IT
WORK?
Sunday, November 10, 13
View

dispatchDraw

onDraw

ViewGroup

ViewGroup

getDrawingCache

onDraw

onDraw

dispatchDraw

View
Sunday, November 10, 13

onDraw
/**
* This is where the invalidate() work actually happens. A full invalidate()
* causes the drawing cache to be invalidated, but this function can be called with
* invalidateCache set to false to skip that invalidation step for cases that do not
* need it (for example, a component that remains at the same dimensions with the same
* content).
*
* @param invalidateCache Whether the drawing cache for this view should be invalidated as
* well. This is usually true for a full invalidate, but may be set to false if the
* View's contents or dimensions have not changed.
*/
void invalidate(boolean invalidateCache) {
if (skipInvalidate()) {
return;
}
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
(invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
(mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
mLastIsOpaque = isOpaque();
mPrivateFlags &= ~PFLAG_DRAWN;
mPrivateFlags |= PFLAG_DIRTY;
if (invalidateCache) {
mPrivateFlags |= PFLAG_INVALIDATED;
mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
final AttachInfo ai = mAttachInfo;
final ViewParent p = mParent;
//noinspection PointlessBooleanExpression,ConstantConditions
if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
if (p != null && ai != null && ai.mHardwareAccelerated) {
// fast-track for GL-enabled applications; just invalidate the whole hierarchy
// with a null dirty rect, which tells the ViewAncestor to redraw everything
p.invalidateChild(this, null);
return;
}
}

}

}

if (p != null && ai != null) {
final Rect r = ai.mTmpInvalRect;
r.set(0, 0, mRight - mLeft, mBottom - mTop);
// Don't call invalidate -- we don't want to internally scroll
// our own bounds
p.invalidateChild(this, r);
}

Sunday, November 10, 13

View
4

Mixed List

Remember one convertView for each type. Headers and Footers
http://www.flickr.com/photos/keesey/
Sunday, November 10, 13
/**
* Sets the data behind this ListView.
*
* The adapter passed to this method may be wrapped by a {@link
WrapperListAdapter},
* depending on the ListView features currently in use. For instance, adding
* headers and/or footers will cause the adapter to be wrapped.
*
* @param adapter The ListAdapter which is responsible for maintaining the
*
data backing this list and for producing a view to represent an
*
item in that data set.
*
* @see #getAdapter()
*/
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos,
adapter);
} else {
mAdapter = adapter;
}
...
}

ListView

Sunday, November 10, 13
public View getView(int position, View convertView, ViewGroup parent) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).view;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getView(adjPosition, convertView, parent);
}
}

}

// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).view;

HeaderViewListAdapter
Sunday, November 10, 13
ListView - addFooterView

Sunday, November 10, 13
5

Animation

Let’s animate items...
Sunday, November 10, 13
- View Animation
- Drawable Animation
- Property Animation

Sunday, November 10, 13
Demo
http://www.flickr.com/photos/farahmandnia/
Sunday, November 10, 13
lv_list.setRecyclerListener(new AbsListView.RecyclerListener() {
@Override
public void onMovedToScrapHeap(View view) {
}
});

/**
* Sets the recycler listener to be notified whenever a View is set aside in
* the recycler for later reuse. This listener can be used to free resources
* associated to the View.
*
* @param listener The recycler listener to be notified of views set aside
*
in the recycler.
*
* @see android.widget.AbsListView.RecycleBin
* @see android.widget.AbsListView.RecyclerListener
*/
public void setRecyclerListener(RecyclerListener listener) {
mRecycler.mRecyclerListener = listener;
}

AbsListView
Sunday, November 10, 13
/**
* Set whether this view is currently tracking transient state that the
* framework should attempt to preserve when possible. This flag is reference counted,
* so every call to setHasTransientState(true) should be paired with a later call
* to setHasTransientState(false).
*
* <p>A view with transient state cannot be trivially rebound from an external
* data source, such as an adapter binding item views in a list. This may be
* because the view is performing an animation, tracking user selection
* of content, or similar.</p>
*
* @param hasTransientState true if this view has transient state
*/
public void setHasTransientState(boolean hasTransientState) {
mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
mTransientStateCount - 1;
if (mTransientStateCount < 0) {
mTransientStateCount = 0;
Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
"unmatched pair of setHasTransientState calls");
}
if ((hasTransientState && mTransientStateCount == 1) ||
(!hasTransientState && mTransientStateCount == 0)) {
// update flag if we've just incremented up from 0 or decremented down to 0
mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
(hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
if (mParent != null) {
try {
mParent.childHasTransientStateChanged(this, hasTransientState);
} catch (AbstractMethodError e) {
Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
" does not fully implement ViewParent", e);
}
}
}
}

View

Sunday, November 10, 13
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
mView.setHasTransientState(true);
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
ArrayList<NameValuesHolder> nameValueList =
(ArrayList<NameValuesHolder>) mPendingAnimations.clone();
mPendingAnimations.clear();
int propertyMask = 0;
int propertyCount = nameValueList.size();
for (int i = 0; i < propertyCount; ++i) {
NameValuesHolder nameValuesHolder = nameValueList.get(i);
propertyMask |= nameValuesHolder.mNameConstant;
}
mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
if (mPendingSetupAction != null) {
mAnimatorSetupMap.put(animator, mPendingSetupAction);
mPendingSetupAction = null;
}
if (mPendingCleanupAction != null) {
...
}

ViewPropertyAnimator
Sunday, November 10, 13
Demo
http://www.flickr.com/photos/farahmandnia/
Sunday, November 10, 13
Renders

6

Our solution
http://www.flickr.com/photos/toughkidcst/
Sunday, November 10, 13
time overhead
viewHolder

GetView
(RenderModel)

Adapter

Render
Builder

Abstract
Render

RenderModel

Render
Impl

Sunday, November 10, 13
7
Sunday, November 10, 13

DIFF IS FUN

http://www.flickr.com/photos/josephwuorigami/
Did someone notice it?

Sunday, November 10, 13
Sunday, November 10, 13
Test Coverage ^_^

Sunday, November 10, 13
They are also human!

Sunday, November 10, 13
http://jobs.tuenti.com
http://corporate.tuenti.com/en/dev/blog
jbarroso@tuenti.com / fcejas@tuenti.com
@flipper83 / @fernando_cejas
Sunday, November 10, 13

More Related Content

Similar to Dinosaurs and Androids: The Listview Evolution

Android basic 4 Navigation Drawer
Android basic 4 Navigation DrawerAndroid basic 4 Navigation Drawer
Android basic 4 Navigation Drawer
Eakapong Kattiya
 
Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013
swentel
 
Pragmatic JavaScript
Pragmatic JavaScriptPragmatic JavaScript
Pragmatic JavaScript
John Hann
 
Android ListView and Custom ListView
Android ListView and Custom ListView Android ListView and Custom ListView
Android ListView and Custom ListView
Sourabh Sahu
 
How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
Oursky
 
How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
Jane Chung
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
Pedro Vicente
 
Day 8: Dealing with Lists and ListViews
Day 8: Dealing with Lists and ListViewsDay 8: Dealing with Lists and ListViews
Day 8: Dealing with Lists and ListViewsAhsanul Karim
 
What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...
Richard McIntyre
 
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
swentel
 
Deep Dive into React Hooks
Deep Dive into React HooksDeep Dive into React Hooks
Deep Dive into React Hooks
Felix Kühl
 
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
Amazon Web Services
 
Ember and containers
Ember and containersEmber and containers
Ember and containers
Matthew Beale
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
Jakub Zalas
 
Ruby on Rails Developer - Allerin
Ruby on Rails Developer - AllerinRuby on Rails Developer - Allerin
Ruby on Rails Developer - Allerin
Lauree R
 
Preparation Data Structures 05 chain linear_list
Preparation Data Structures 05 chain linear_listPreparation Data Structures 05 chain linear_list
Preparation Data Structures 05 chain linear_list
Andres Mendez-Vazquez
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
dcs plus
 
Introduction to Android Fragments
Introduction to Android FragmentsIntroduction to Android Fragments
Introduction to Android Fragments
Sergi Martínez
 

Similar to Dinosaurs and Androids: The Listview Evolution (20)

Android basic 4 Navigation Drawer
Android basic 4 Navigation DrawerAndroid basic 4 Navigation Drawer
Android basic 4 Navigation Drawer
 
Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013
 
Pragmatic JavaScript
Pragmatic JavaScriptPragmatic JavaScript
Pragmatic JavaScript
 
Android ListView and Custom ListView
Android ListView and Custom ListView Android ListView and Custom ListView
Android ListView and Custom ListView
 
How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
 
How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
 
Day 8: Dealing with Lists and ListViews
Day 8: Dealing with Lists and ListViewsDay 8: Dealing with Lists and ListViews
Day 8: Dealing with Lists and ListViews
 
What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...
 
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
 
Deep Dive into React Hooks
Deep Dive into React HooksDeep Dive into React Hooks
Deep Dive into React Hooks
 
Dig1108 Lesson 3
Dig1108 Lesson 3Dig1108 Lesson 3
Dig1108 Lesson 3
 
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
(AFF301) Fire Phone: The Dynamic Perspective API, Under the Hood | AWS re:Inv...
 
Ember and containers
Ember and containersEmber and containers
Ember and containers
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
Ruby on Rails Developer - Allerin
Ruby on Rails Developer - AllerinRuby on Rails Developer - Allerin
Ruby on Rails Developer - Allerin
 
Preparation Data Structures 05 chain linear_list
Preparation Data Structures 05 chain linear_listPreparation Data Structures 05 chain linear_list
Preparation Data Structures 05 chain linear_list
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
 
List adapter with multiple objects
List adapter with multiple objectsList adapter with multiple objects
List adapter with multiple objects
 
Introduction to Android Fragments
Introduction to Android FragmentsIntroduction to Android Fragments
Introduction to Android Fragments
 

More from Fernando Cejas

The Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on AndroidThe Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on Android
Fernando Cejas
 
It is about philosophy: culture of a good programmer
It is about philosophy: culture of a good programmerIt is about philosophy: culture of a good programmer
It is about philosophy: culture of a good programmer
Fernando Cejas
 
Material Design for Old Schoolers
Material Design for Old SchoolersMaterial Design for Old Schoolers
Material Design for Old Schoolers
Fernando Cejas
 
How to Become the MacGyver of Android Custom Views
How to Become the MacGyver of Android Custom ViewsHow to Become the MacGyver of Android Custom Views
How to Become the MacGyver of Android Custom Views
Fernando Cejas
 
Android UX-UI Design for Fun and Profit
Android UX-UI Design for Fun and ProfitAndroid UX-UI Design for Fun and Profit
Android UX-UI Design for Fun and Profit
Fernando Cejas
 
How ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second EditionHow ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second Edition
Fernando Cejas
 
How ANDROID TESTING changed how we think about Death
How ANDROID TESTING changed how we think about DeathHow ANDROID TESTING changed how we think about Death
How ANDROID TESTING changed how we think about Death
Fernando Cejas
 
Inside Android Testing
Inside Android TestingInside Android Testing
Inside Android Testing
Fernando Cejas
 
Webview: The fifth element
Webview: The fifth elementWebview: The fifth element
Webview: The fifth element
Fernando Cejas
 
Nfc on Android
Nfc on AndroidNfc on Android
Nfc on Android
Fernando Cejas
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
Fernando Cejas
 
Android Cloud To Device Messaging
Android Cloud To Device MessagingAndroid Cloud To Device Messaging
Android Cloud To Device Messaging
Fernando Cejas
 
Android Quick Introduction
Android Quick IntroductionAndroid Quick Introduction
Android Quick Introduction
Fernando Cejas
 
Desarrollo android almacenamiento de datos
Desarrollo android    almacenamiento de datosDesarrollo android    almacenamiento de datos
Desarrollo android almacenamiento de datos
Fernando Cejas
 
Android simple 2d Layout animation
Android simple 2d Layout animationAndroid simple 2d Layout animation
Android simple 2d Layout animationFernando Cejas
 

More from Fernando Cejas (15)

The Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on AndroidThe Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on Android
 
It is about philosophy: culture of a good programmer
It is about philosophy: culture of a good programmerIt is about philosophy: culture of a good programmer
It is about philosophy: culture of a good programmer
 
Material Design for Old Schoolers
Material Design for Old SchoolersMaterial Design for Old Schoolers
Material Design for Old Schoolers
 
How to Become the MacGyver of Android Custom Views
How to Become the MacGyver of Android Custom ViewsHow to Become the MacGyver of Android Custom Views
How to Become the MacGyver of Android Custom Views
 
Android UX-UI Design for Fun and Profit
Android UX-UI Design for Fun and ProfitAndroid UX-UI Design for Fun and Profit
Android UX-UI Design for Fun and Profit
 
How ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second EditionHow ANDROID TESTING changed how we think about Death - Second Edition
How ANDROID TESTING changed how we think about Death - Second Edition
 
How ANDROID TESTING changed how we think about Death
How ANDROID TESTING changed how we think about DeathHow ANDROID TESTING changed how we think about Death
How ANDROID TESTING changed how we think about Death
 
Inside Android Testing
Inside Android TestingInside Android Testing
Inside Android Testing
 
Webview: The fifth element
Webview: The fifth elementWebview: The fifth element
Webview: The fifth element
 
Nfc on Android
Nfc on AndroidNfc on Android
Nfc on Android
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
 
Android Cloud To Device Messaging
Android Cloud To Device MessagingAndroid Cloud To Device Messaging
Android Cloud To Device Messaging
 
Android Quick Introduction
Android Quick IntroductionAndroid Quick Introduction
Android Quick Introduction
 
Desarrollo android almacenamiento de datos
Desarrollo android    almacenamiento de datosDesarrollo android    almacenamiento de datos
Desarrollo android almacenamiento de datos
 
Android simple 2d Layout animation
Android simple 2d Layout animationAndroid simple 2d Layout animation
Android simple 2d Layout animation
 

Recently uploaded

SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
Peter Spielvogel
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
UiPathCommunity
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 

Recently uploaded (20)

SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 

Dinosaurs and Androids: The Listview Evolution

  • 1. Dinosaurs and Androids:The ListView evolution Jorge J. Barroso / Fernando Cejas Tech Lead Android Core / Android Developer jbarroso@tuenti.com / fcejas@tuenti.com @flipper83 / @fernando_cejas / @TuentiEng Code samples: https://github.com/android10/Inside_Android_ListView Sunday, November 10, 13
  • 4. public abstract class AbsListView extends AdapterView<ListAdapter> public abstract class AdapterView <T extends Adapter> extends ViewGroup Sunday, November 10, 13
  • 6. /** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin. * * @param position Logical position in the list * @param y Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param childrenLeft Left edge where children should be positioned * @param selected Is this position selected? * @return View that was added */ private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected) { View child; if (!mDataChanged) { // Try to use an existing view for this position child = mRecycler.getActiveView(position); if (child != null) { // Found it -- we're using an existing child // This just needs to be positioned setupChild(child, position, y, flow, childrenLeft, selected, true); return child; } } // Make a new view for this position, or convert an unused view if possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); return child; } Sunday, November 10, 13 ListView
  • 7. /** * Get a view and have it show the data associated with the specified * position. This is called when we have already discovered that the view is * not available for reuse in the recycle bin. The only choices left are * converting an old view or making a new one. * * @param position The position to display * @param isScrap Array of at least 1 boolean, the first entry will become true if * the returned view was taken from the scrap heap, false if otherwise. * * @return A view displaying the data associated with the specified position */ View obtainView(int position, boolean[] isScrap) { isScrap[0] = false; View scrapView; scrapView = mRecycler.getTransientStateView(position); if (scrapView != null) { return scrapView; } scrapView = mRecycler.getScrapView(position); View child; if (scrapView != null) { child = mAdapter.getView(position, scrapView, this); ... } Sunday, November 10, 13 AbsListView
  • 10. 2 ViewHolders Is this really necessary? http://www.flickr.com/photos/rojam/ Sunday, November 10, 13
  • 11. Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern. Sunday, November 10, 13
  • 12. @Override protected View findViewTraversal(int id) { if (id == mID) { return this; } final View[] where = mChildren; final int len = mChildrenCount; for (int i = 0; i < len; i++) { View v = where[i]; if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) { v = v.findViewById(id); if (v != null) { return v; } } } return null; } ViewGroup Sunday, November 10, 13
  • 14. 3 Optimization Where are we wasting time? http://www.flickr.com/photos/kabacchi/ Sunday, November 10, 13
  • 19. /** * This is where the invalidate() work actually happens. A full invalidate() * causes the drawing cache to be invalidated, but this function can be called with * invalidateCache set to false to skip that invalidation step for cases that do not * need it (for example, a component that remains at the same dimensions with the same * content). * * @param invalidateCache Whether the drawing cache for this view should be invalidated as * well. This is usually true for a full invalidate, but may be set to false if the * View's contents or dimensions have not changed. */ void invalidate(boolean invalidateCache) { if (skipInvalidate()) { return; } if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) { mLastIsOpaque = isOpaque(); mPrivateFlags &= ~PFLAG_DRAWN; mPrivateFlags |= PFLAG_DIRTY; if (invalidateCache) { mPrivateFlags |= PFLAG_INVALIDATED; mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; } final AttachInfo ai = mAttachInfo; final ViewParent p = mParent; //noinspection PointlessBooleanExpression,ConstantConditions if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { if (p != null && ai != null && ai.mHardwareAccelerated) { // fast-track for GL-enabled applications; just invalidate the whole hierarchy // with a null dirty rect, which tells the ViewAncestor to redraw everything p.invalidateChild(this, null); return; } } } } if (p != null && ai != null) { final Rect r = ai.mTmpInvalRect; r.set(0, 0, mRight - mLeft, mBottom - mTop); // Don't call invalidate -- we don't want to internally scroll // our own bounds p.invalidateChild(this, r); } Sunday, November 10, 13 View
  • 20. 4 Mixed List Remember one convertView for each type. Headers and Footers http://www.flickr.com/photos/keesey/ Sunday, November 10, 13
  • 21. /** * Sets the data behind this ListView. * * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter}, * depending on the ListView features currently in use. For instance, adding * headers and/or footers will cause the adapter to be wrapped. * * @param adapter The ListAdapter which is responsible for maintaining the * data backing this list and for producing a view to represent an * item in that data set. * * @see #getAdapter() */ @Override public void setAdapter(ListAdapter adapter) { if (mAdapter != null && mDataSetObserver != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); } resetList(); mRecycler.clear(); if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); } else { mAdapter = adapter; } ... } ListView Sunday, November 10, 13
  • 22. public View getView(int position, View convertView, ViewGroup parent) { // Header (negative positions will throw an ArrayIndexOutOfBoundsException) int numHeaders = getHeadersCount(); if (position < numHeaders) { return mHeaderViewInfos.get(position).view; } // Adapter final int adjPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getCount(); if (adjPosition < adapterCount) { return mAdapter.getView(adjPosition, convertView, parent); } } } // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException) return mFooterViewInfos.get(adjPosition - adapterCount).view; HeaderViewListAdapter Sunday, November 10, 13
  • 25. - View Animation - Drawable Animation - Property Animation Sunday, November 10, 13
  • 27. lv_list.setRecyclerListener(new AbsListView.RecyclerListener() { @Override public void onMovedToScrapHeap(View view) { } }); /** * Sets the recycler listener to be notified whenever a View is set aside in * the recycler for later reuse. This listener can be used to free resources * associated to the View. * * @param listener The recycler listener to be notified of views set aside * in the recycler. * * @see android.widget.AbsListView.RecycleBin * @see android.widget.AbsListView.RecyclerListener */ public void setRecyclerListener(RecyclerListener listener) { mRecycler.mRecyclerListener = listener; } AbsListView Sunday, November 10, 13
  • 28. /** * Set whether this view is currently tracking transient state that the * framework should attempt to preserve when possible. This flag is reference counted, * so every call to setHasTransientState(true) should be paired with a later call * to setHasTransientState(false). * * <p>A view with transient state cannot be trivially rebound from an external * data source, such as an adapter binding item views in a list. This may be * because the view is performing an animation, tracking user selection * of content, or similar.</p> * * @param hasTransientState true if this view has transient state */ public void setHasTransientState(boolean hasTransientState) { mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : mTransientStateCount - 1; if (mTransientStateCount < 0) { mTransientStateCount = 0; Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + "unmatched pair of setHasTransientState calls"); } if ((hasTransientState && mTransientStateCount == 1) || (!hasTransientState && mTransientStateCount == 0)) { // update flag if we've just incremented up from 0 or decremented down to 0 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); if (mParent != null) { try { mParent.childHasTransientStateChanged(this, hasTransientState); } catch (AbstractMethodError e) { Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + " does not fully implement ViewParent", e); } } } } View Sunday, November 10, 13
  • 29. /** * Starts the underlying Animator for a set of properties. We use a single animator that * simply runs from 0 to 1, and then use that fractional value to set each property * value accordingly. */ private void startAnimation() { mView.setHasTransientState(true); ValueAnimator animator = ValueAnimator.ofFloat(1.0f); ArrayList<NameValuesHolder> nameValueList = (ArrayList<NameValuesHolder>) mPendingAnimations.clone(); mPendingAnimations.clear(); int propertyMask = 0; int propertyCount = nameValueList.size(); for (int i = 0; i < propertyCount; ++i) { NameValuesHolder nameValuesHolder = nameValueList.get(i); propertyMask |= nameValuesHolder.mNameConstant; } mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList)); if (mPendingSetupAction != null) { mAnimatorSetupMap.put(animator, mPendingSetupAction); mPendingSetupAction = null; } if (mPendingCleanupAction != null) { ... } ViewPropertyAnimator Sunday, November 10, 13
  • 33. 7 Sunday, November 10, 13 DIFF IS FUN http://www.flickr.com/photos/josephwuorigami/
  • 34. Did someone notice it? Sunday, November 10, 13
  • 36. Test Coverage ^_^ Sunday, November 10, 13
  • 37. They are also human! Sunday, November 10, 13