Date post: | 07-Feb-2017 |
Category: |
Software |
Upload: | simek-adam |
View: | 85 times |
Download: | 0 times |
“Well, that’s: user input, networking, data processing, database/disk I/O, view inflation, layout, drawing,… Thwre also other applications, cpus are slow, memories are too, everything takes forever. And then you are supposed to save battery.”
ViewHolder
Best practice from ListViewLightweight view wrapper for list itemsRecycler holds a limited amount of them and reuses themOne ViewHolder is used for more items (not at a time)It has it’s own lifecyle
ViewHolder Lifecycle
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {}
@Override public void onBindViewHolder(ViewHolder holder, int position) {}
@Override public void onViewAttachedToWindow(ViewHolder holder) {}
@Override public void onViewDetachedFromWindow(ViewHolder holder) {}
@Override public void onViewRecycled(ViewHolder holder) {}
@Override public boolean onFailedToRecycleView(ViewHolder holder) {}
ViewHolder Lifecycle
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {}
@Override public void onBindViewHolder(ViewHolder holder, int position) {}
@Override public void onViewAttachedToWindow(ViewHolder holder) {}
@Override public void onViewDetachedFromWindow(ViewHolder holder) {}
@Override public void onViewRecycled(ViewHolder holder) {}
@Override public boolean onFailedToRecycleView(ViewHolder holder) {}
What not to do?
Disk I/O - SQLite, SharedPreferences, Content Providersfor (Comment comment : item.getComments()) {}
Parsing of text, JSONu,…, complicated formatting,..Html.fromHtml()
Complicated layouts 🙂
“I can go home, it’s runs smooth on my phone.”Critical code can be hidden (deep) in the abstraction
What to do?
Everything expensive has to run in background…,or it has to be preprocessed
You don’t have to show it right away → use tmp placeholdersvoid onScrollStateChanged(…, int newState)
mHandler.postDelayed(deferredBind, DELAY }
☝ it’s crucial to keep this balanced
Test on various devices (low-end, tablets)…and with various dataStrictMode
Guess what’s wrong?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position) { mImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mClickHandler.onItemClicked(v, position, photo); } }); }
Guess what’s wrong?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position) { mImageView.setOnClickListener(mClickListener); // use member var instead }
Guess what’s wrong?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position, ItemClickListener listener) { mImageView.setOnClickListener(listener); // even better.. }
Guess what’s wrong?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position) { mImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mClickHandler.onItemClicked(v, position, photo); } }); }
Guess what’s wrong?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position) { mImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mClickHandler.onItemClicked(v, getAdapterPosition(), photo); } }); }
AsyncTask
Runs tasks in serial → super slowHm…executeOnExecutor(THREAD_POOL_EXECUTOR); Big operational overheadTricky and unreliable task cancelling
💥
java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@36e83ee rejected from java.util.concurrent.ThreadPoolExecutor@a54e08f[Running, pool size = 13, active threads = 13, queued tasks = 128, completed tasks = 1055]
DIY
Custom “taskmanager”
… mDecodeThreadPool = new ThreadPoolExecutor( NUMBER_OF_CORES, // Initial pool size NUMBER_OF_CORES, // Max pool size KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, mDecodeWorkQueue); // 128 size in AsyncTask …
mDecodeThreadPool.execute(DownloadTask); // execute task …
Sneaky things
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
View.requestLayout() + hasFixedSize
void triggerUpdateProcessor() { if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) { ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable); } else { mAdapterUpdateDuringMeasure = true; requestLayout(); } }
Sneaky things
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
TextView.setAllCaps()
public void setAllCaps(boolean allCaps) { if (allCaps) { setTransformationMethod(new AllCapsTransformationMethod(getContext())); } else { setTransformationMethod(null); } }
Sneaky things
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
Prefetch
Create and bind “up front”Estimates how long it will run to make sure it won’t cause delaysLollipop+ (RenderThread), support lib 25.1setItemPrefetchEnabled(true) Supported by built-in LayoutManageres (API for custom ones)Watch out for onBindViewHolder - no animations,…setInitialPrefetchItemCount(N)
You can see the difference with your naked eye 👀