+ All Categories
Transcript
Page 1: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 2: Adam Šimek: Optimalizace skrolování, RecyclerView

Pohádka o plynulém skrolování

ADAM ŠIMEK

Page 3: Adam Šimek: Optimalizace skrolování, RecyclerView

Umět seznamy je důležité

Page 4: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 5: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 6: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 7: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 8: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 9: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 10: Adam Šimek: Optimalizace skrolování, RecyclerView

Kulmanův test

Page 11: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 12: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 13: Adam Šimek: Optimalizace skrolování, RecyclerView

Jakto?

Page 14: Adam Šimek: Optimalizace skrolování, RecyclerView

¯\_(ツ)_/¯

Page 15: Adam Šimek: Optimalizace skrolování, RecyclerView

16

Page 16: Adam Šimek: Optimalizace skrolování, RecyclerView

16ms

Page 17: Adam Šimek: Optimalizace skrolování, RecyclerView

“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

16ms?

Page 19: Adam Šimek: Optimalizace skrolování, RecyclerView

Tak jdeme na to…

Page 20: Adam Šimek: Optimalizace skrolování, RecyclerView

ListView

Page 21: Adam Šimek: Optimalizace skrolování, RecyclerView

ListView

Page 22: Adam Šimek: Optimalizace skrolování, RecyclerView

RecyclerView

Page 23: Adam Šimek: Optimalizace skrolování, RecyclerView

Architektura RecyclerView

Page 24: Adam Šimek: Optimalizace skrolování, RecyclerView

ViewHolder

Page 25: Adam Šimek: Optimalizace skrolování, RecyclerView

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

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

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

“Nejrychlejší kód je kód, který se nevolá.” Sokrates

Page 29: Adam Šimek: Optimalizace skrolování, RecyclerView

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

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

Co je doma, to se počítá

Page 32: Adam Šimek: Optimalizace skrolování, RecyclerView
Page 33: Adam Šimek: Optimalizace skrolování, RecyclerView

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

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

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

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

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

Dvakrát měř, jednou řež.

Page 39: Adam Šimek: Optimalizace skrolování, RecyclerView

AsyncTask

Page 40: Adam Šimek: Optimalizace skrolování, RecyclerView

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

💥

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

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

Další záludnosti

Page 44: Adam Šimek: Optimalizace skrolování, RecyclerView

Další záludnosti

View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize

) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()

Page 45: Adam Šimek: Optimalizace skrolování, RecyclerView

View.requestLayout()

Page 46: Adam Šimek: Optimalizace skrolování, RecyclerView

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

Další záludnosti

View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize

) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()

Page 48: Adam Šimek: Optimalizace skrolování, RecyclerView

TextView.setAllCaps()

public void setAllCaps(boolean allCaps) { if (allCaps) { setTransformationMethod(new AllCapsTransformationMethod(getContext())); } else { setTransformationMethod(null); } }

Page 49: Adam Šimek: Optimalizace skrolování, RecyclerView

Další záludnosti

View.requestLayout() ——————— RecyclerView.setHasFixedSize( boolean hasFixedSize

) ——————— TextView.setAllCaps(boolean allCaps) ——————— notifyDatasetChanged()

Page 50: Adam Šimek: Optimalizace skrolování, RecyclerView

“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

Prefetch

Page 52: Adam Šimek: Optimalizace skrolování, RecyclerView

Systrace

Page 53: Adam Šimek: Optimalizace skrolování, RecyclerView

Systrace - missed frame

Page 54: Adam Šimek: Optimalizace skrolování, RecyclerView

Prefetch OFF

Page 55: Adam Šimek: Optimalizace skrolování, RecyclerView

Prefetch ON

Page 56: Adam Šimek: Optimalizace skrolování, RecyclerView

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

Page 57: Adam Šimek: Optimalizace skrolování, RecyclerView

Díky! @simekadam

strava.com/athletes/simekadam

Page 58: Adam Šimek: Optimalizace skrolování, RecyclerView

@simekadam strava.com/athletes/simekadam


Top Related