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

No more Adapter with Epoxy and Data Binding

No more Adapter with Epoxy and Data Binding

E28404a128b6014e6f499d2a967c72a0?s=128

Takuji Nishibayashi

March 01, 2019
Tweet

Transcript

  1. No more Adapter with Epoxy and Data Binding @takuji31 ژ౎Dev͔;͐

    #5
  2. ࣗݾ঺հ

  3. ࣗݾ঺հ • @takuji31 id:takuji31 • Takuji Nishibayashi • Hatena Co.,

    Ltd. • App Team • δϟϯϓϧʔΩʔʂ • ίϛοΫDAYS • ΧΫϤϜ
  4. ࣗݾ঺հ • Android • Kotlin • ! https://blog.takuji31.jp • "

    https://nazuna.takuji31.jp • # $ https://photo.takuji31.jp
  5. RecyclerView

  6. ࢖ͬͯͳ͍ਓ͍·ͤΜΑͶʁ

  7. ViewHolder + Adapter

  8. ΦϓγϣϯͰ DiffUtil

  9. blog.takuji31.jp/entry/kanmoba17

  10. ෳࡶͳը໘

  11. None
  12. Ͳ͏࣮ݱ͢Δʁ

  13. खͰؤுΔ

  14. ViewHolderΛview type͝ͱʹ࡞Δ

  15. onCreateViewHolderͰ֘౰͢Δ ViewHolderΛ࡞Δ

  16. onBindViewHolderͰViewHolderͷ ܕΛݟͯ஋Λઃఆ

  17. มߋݕ஌

  18. DiffUtilͰؤுΔ

  19. !

  20. Section Library

  21. ※ ͍͔ͭ͘ϥΠϒϥϦʔ͕͋Γ·͢ ͕Ұൠతͳ࿩Ͱ͢

  22. view typeͷ୅ΘΓʹSectionͱ͍͏ ΫϥεΛ࢖͏

  23. Section class WorkSection(val items:List<Work>): Section<WorkViewHolder>() { override fun onCreateViewHolder(inflator: LayoutInflator,

    parent: ViewGroup): WorkViewHolder { return WorkViewHolder(inflator.inflate(R.layout.recycle_item_work, parent, false)) } override fun onBindViewHolder(viewHolder: WorkViewHolder, position: Int) { val work = items[position] viewHolder.title = work.title Picasso.get().load(work.imageUri).into(viewHolder.imageView) } }
  24. Adapter val adapter = Adapter() adapter.addSection(BannerSection(works)) adapter.addSection(WorkSection(works.take(10))) adapter.addSection(EntrySection(works)) adapter.addSection(WorkSection(works.drop(10)))

  25. ύοͱݟ؆୯ͦ͏

  26. ΫϦοΫΠϕϯτͷ఻ୡͲ͏͢Δ…ʁ class WorkSection(val items:List<Work>, val onClick: (Work) -> Unit): Section<WorkViewHolder>()

    { override fun onCreateViewHolder(inflator: LayoutInflator, parent: ViewGroup): WorkViewHolder { return WorkViewHolder(inflator.inflate(R.layout.recycle_item_work, parent, false)) } override fun onBindViewHolder(viewHolder: WorkViewHolder, position: Int) { val work = items[position] viewHolder.title = work.title Picasso.get().load(work.imageUri).into(viewHolder.imageView) viewHolder.itemView.setOnClickListener { onClick() } } }
  27. Adapter val adapter = Adapter( {work -> viewModel.onWorkSelected(work)}, {entry ->

    viewModel.onEntrySelected(entry)}, {banner -> viewModel.onBannerSelected(banner)}, ) adapter.addSection(BannerSection(works)) adapter.addSection(WorkSection(works.take(10))) adapter.addSection(EntrySection(works)) adapter.addSection(WorkSection(works.drop(10)))
  28. ͪΐͬͱ໘౗

  29. ͦ΋ͦ΋

  30. Adapter -> Section -> ViewHolder

  31. ֊૚͕૿͑Δ

  32. ঢ়ଶΛόϥόϥʹ͍࣋ͬͯͨΓ͢Δ ͱ෮ݩͰࢮ͵

  33. Ϋϥε਺૿͑Δ

  34. ॳݟͰΊͬͪΌΉ͍ͣ

  35. Epoxy

  36. github.com/airbnb/epoxy

  37. No more

  38. ViewHolder

  39. notifyDataSetChanged()

  40. Adapter

  41. Carousel support

  42. Data Binding Friendly

  43. Kotlin DSL support!!!

  44. build.gradle dependencies { implementation "com.airbnb.android:epoxy:3.3.0" implementation "com.airbnb.android:epoxy-databinding:3.3.0" kapt "com.airbnb.android:epoxy-processor:3.3.0" }

  45. package-info.java @EpoxyDataBindingPattern(rClass = R.class, layoutPrefix = "recycler") package jp.takuji31.epoxyexample; import

    com.airbnb.epoxy.EpoxyDataBindingPattern;
  46. recycler_item_work.xml <layout> <data> <variable name="work" type="jp.takuji31.epoxyexample.model.Work" /> <variable name="onClick" type="android.view.View.OnClickListener"

    /> </data> <androidx.cardview.widget.CardView android:onClick="@{onClick}"> <androidx.constraintlayout.widget.ConstraintLayout> <ImageView app:imageUri="@{work.imageUri}"/> <TextView android:text="@{work.title}"/> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView> </layout>
  47. Activity or Fragment recyclerView.withModels { works.forEach { work -> itemWork

    { id("work_${work.id}") work(work) } } }
  48. None
  49. !

  50. Carousel

  51. Carousel recyclerView.withModels { carousel { id("entryCaroucel") withModelsFrom(entries) { entry ->

    ItemEntryBindingModel_() .id("entry_${entry.id}") .entry(entry) } } }
  52. None
  53. ؆୯͗͢Ͱ͸

  54. ෳࡶͳϨΠΞ΢τ

  55. ෳࡶͳϨΠΞ΢τ Carousel.setDefaultGlobalSnapHelperFactory(null) carousel { id("bannerCarousel") withModelsFrom(banners) { ItemBannerBindingModel_() .id("banner_${it.id}") .banner(it)

    } } works.take(10).forEach { work -> itemWork { id("work_${work.id}") work(work) } }
  56. ෳࡶͳϨΠΞ΢τ headerBlogEntry { id("blog_header") } carousel { id("entryCaroucel") withModelsFrom(entries) {

    entry -> ItemEntryBindingModel_() .id("entry_${entry.id}") .entry(entry) } } works.drop(10).forEach { work -> itemWork { id("work_${work.id}") work(work) } }
  57. ׬੒ʂ

  58. https://github.com/takuji31/epoxy- example

  59. Enjoy RecyclerView life

  60. ! ࠾༻৘ใ

  61. גࣜձࣾ͸ͯͳͰ͸ɺ ͱ΋ʹʮ௅ઓʯͰ͖Δ ஥ؒΛืू͍ͯ͠·͢

  62. ͜ΜͳਓΛ୳͍ͯ͠·͢ • AndroidΞϓϦΛ࡞Γ͍ͨਓ • iOSΞϓϦΛ࡞Γ͍ͨਓ • ͋Δ͍͸྆ํ • ͳΜͳΒαʔόʔαΠυ΋

  63. https://hatenacorp.jp/recruit/