Adam Šimek: Optimalizace skrolování, RecyclerView
Transcript of Adam Šimek: Optimalizace skrolování, RecyclerView
![Page 1: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/1.jpg)
![Page 2: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/2.jpg)
Pohádka o plynulém skrolování
ADAM ŠIMEK
![Page 3: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/3.jpg)
Umět seznamy je důležité
![Page 4: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/4.jpg)
![Page 5: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/5.jpg)
![Page 6: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/6.jpg)
![Page 7: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/7.jpg)
![Page 8: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/8.jpg)
![Page 9: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/9.jpg)
![Page 10: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/10.jpg)
Kulmanův test
![Page 11: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/11.jpg)
![Page 12: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/12.jpg)
![Page 13: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/13.jpg)
Jakto?
![Page 14: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/14.jpg)
¯\_(ツ)_/¯
![Page 15: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/15.jpg)
16
![Page 16: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/16.jpg)
16ms
![Page 17: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/17.jpg)
“A to máte: user input, networking, data processing, database/disk I/O, view inflation, layout, drawing,… Jsou tam taky další aplikace, procesory jsou pomalý, flashky taky, všechno to strasně dlouho trvá. A ještě ke všemu jedeme na baterku.”
![Page 18: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/18.jpg)
16ms?
![Page 19: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/19.jpg)
Tak jdeme na to…
![Page 20: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/20.jpg)
ListView
![Page 21: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/21.jpg)
ListView
![Page 22: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/22.jpg)
RecyclerView
![Page 23: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/23.jpg)
Architektura RecyclerView
![Page 24: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/24.jpg)
ViewHolder
![Page 25: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/25.jpg)
ViewHolder
Best practice z ListViewTakový lightweight controller k jednotlivým položkámRecyclerView si jich drží omezený počet a recykluje jeJeden ViewHolder je použit pro víc položek (ne najednou)Má svůj životní cyklus
![Page 26: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/26.jpg)
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) {}
![Page 27: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/27.jpg)
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) {}
![Page 28: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/28.jpg)
“Nejrychlejší kód je kód, který se nevolá.” Sokrates
![Page 29: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/29.jpg)
Co nedělat?
Disk I/O - SQLite, SharedPreferences, Content Providersfor (Comment comment : item.getComments()) {}
Parsování textu, JSONu,…, složité formátování,..Html.fromHtml()
Složité layouty 🙂
“Když to běží na u mě plynule, tak v pohodě.”Kritický kód může být schovaný v abstrakci
![Page 30: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/30.jpg)
Co dělat?
Složité operace musí bežet na pozadí (vše z předchozího slajdu)…,nebo už musí být předpřipravené
Není potřeba vše vykreslovat hned → placeholder na chvíli stačívoid onScrollStateChanged(…, int newState)
mHandler.postDelayed(deferredBind, DELAY }
☝ důležitá je vyvážennost
Testovat na různých zařízeních (low-end, tablety)…a taky ruzných datechStrictMode
![Page 31: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/31.jpg)
Co je doma, to se počítá
![Page 32: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/32.jpg)
![Page 33: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/33.jpg)
Co je špatně?
//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); } }); }
![Page 34: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/34.jpg)
Co je špatně?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position) { mImageView.setOnClickListener(mClickListener); // use member var instead }
![Page 35: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/35.jpg)
Co je špatně?
//ViewHolder code called in onBindViewHolder()
@Override public void bindData(Object data, final int position, ItemClickListener listener) { mImageView.setOnClickListener(listener); // even better.. }
![Page 36: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/36.jpg)
Co je špatně?
//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); } }); }
![Page 37: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/37.jpg)
Co je špatně?
//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); } }); }
![Page 38: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/38.jpg)
Dvakrát měř, jednou řež.
![Page 39: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/39.jpg)
AsyncTask
![Page 40: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/40.jpg)
AsyncTask
Standardně běží tasky sériově → všechno trváHm…executeOnExecutor(THREAD_POOL_EXECUTOR); Je tam celkem velký overheadTasky se docela blbě přerušují
![Page 41: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/41.jpg)
💥
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]
![Page 42: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/42.jpg)
DIY
Vlastní “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 …
![Page 43: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/43.jpg)
Další záludnosti
![Page 44: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/44.jpg)
Další záludnosti
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
![Page 45: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/45.jpg)
View.requestLayout()
![Page 46: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/46.jpg)
View.requestLayout() + hasFixedSize
void triggerUpdateProcessor() { if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) { ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable); } else { mAdapterUpdateDuringMeasure = true; requestLayout(); } }
![Page 47: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/47.jpg)
Další záludnosti
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
![Page 48: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/48.jpg)
TextView.setAllCaps()
public void setAllCaps(boolean allCaps) { if (allCaps) { setTransformationMethod(new AllCapsTransformationMethod(getContext())); } else { setTransformationMethod(null); } }
![Page 49: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/49.jpg)
Další záludnosti
View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize
) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()
![Page 50: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/50.jpg)
“Today I will do what others won't, so tomorrow I can accomplish what
others can’t"
![Page 51: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/51.jpg)
Prefetch
![Page 52: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/52.jpg)
Systrace
![Page 53: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/53.jpg)
Systrace - missed frame
![Page 54: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/54.jpg)
Prefetch OFF
![Page 55: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/55.jpg)
Prefetch ON
![Page 56: Adam Šimek: Optimalizace skrolování, RecyclerView](https://reader034.fdocuments.net/reader034/viewer/2022042722/58a52ead1a28aba8628b5455/html5/thumbnails/56.jpg)
Prefetch
create a bind “do zásoby”odhaduje jak dlouho ty operace trvají (aby se to stihlo)Lollipop+ (RenderThread), support lib 25.1setItemPrefetchEnabled(true) podporováno ve výchozích LayoutManagerech (API pro custom)pozor na onBindViewHolder - žádné animace,…setInitialPrefetchItemCount(N) rozdíl je fakt vidět