Data Binding with RecyclerView

Data Binding with RecyclerView

shibuya.apk #16

85cab5fdf09afe3ee78ce3667681915a?s=128

Keisuke Kobayashi

June 22, 2017
Tweet

Transcript

  1. Data Binding with RecyclerView Keisuke Kobayashi / @kobakei shibuya.apk #16

  2. About me • Keisuke Kobayashi • GitHub, Qiita: @kobakei •

    Twitter: @kobakei122 • Kyash, Inc
  3. ࠓ೔࿩͢͜ͱ • σʔλόΠϯσΟϯάΛRecyclerViewͰ࢖͏ ࿩Λ͠·͢

  4. DroidKaigi
 Contributors List

  5. None
  6. ྫ: DroidKaigi contributors list • ը໘શମ • ϢʔβʔϦετ • ΞΠςϜ

    • Ϣʔβʔ • ໊લ • ը૾URL
  7. Files • ը໘શମ • user_list_activity.xml • UserListActivity • UserAdapter •

    UserListViewModel • ֤ΞΠςϜ • user_list_item.xml
  8. Files • ը໘શମ • user_list_activity.xml • UserListActivity • UserAdapter •

    UserListViewModel • ֤ΞΠςϜ • user_list_item.xml
  9. user_list_activity.xml • RecyclerViewΛஔ͚ͩ͘ <layout> <data> <variable name="viewModel" type="com.example.app.UserListViewModel"/> </data> <RecyclerView/>

    </layout>
  10. user_list_item.xml • ֤Ϣʔβʔͱ֤ΞΠςϜͷόΠϯσΟϯά <layout> <data> <variable name="user" type="com.example.app.User"/> </data> <LinearLayout>

    <ImageView app:imageUrl="@{user.imageUrl}"/> <TextView android:text="@{user.name}"/> </LinearLayout> </layout>
  11. user_list_item.xml • ֤Ϣʔβʔͱ֤ΞΠςϜͷόΠϯσΟϯά <layout> <data> <variable name="user" type="com.example.app.User"/> </data> <LinearLayout>

    <ImageView app:imageUrl="@{user.imageUrl}"/> <TextView android:text="@{user.name}"/> </LinearLayout> </layout> UserʹόΠϯυ
  12. UserListViewModel • ͜͜Ͱ͸ϢʔβʔϦετ͸ݻఆ class UserListViewModel: BaseObservable() { val users =

    listOf( User(“taro”, “https://example.com/1.png”), User(“jiro”, “https://example.com/2.png”), User(“saburo”, “https://example.com/3.png”) ) }
  13. UserListActivity lateinit var viewModel: UserListViewModel override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<UserListActivityBinding>( this, R.layout.user_list_activity) // Set up viewModel here (ex. inject by Dagger) binding.recyclerView.setAdapter(UserAdapter(viewModel.users)) }
  14. UserListActivity lateinit var viewModel: UserListViewModel override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<UserListActivityBinding>( this, R.layout.user_list_activity) // Set up viewModel here (ex. inject by Dagger) binding.recyclerView.setAdapter(UserAdapter(viewModel.users)) } ը໘ͷϏϡʔϞσϧ ͜͜ͰॳظԽ
  15. UserListActivity lateinit var viewModel: UserListViewModel override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<UserListActivityBinding>( this, R.layout.user_list_activity) // Set up viewModel here (ex. inject by Dagger) binding.recyclerView.setAdapter(UserAdapter(viewModel.users)) } ը໘ͷϏϡʔϞσϧͷusersΛΞμϓλʔʹηοτ
  16. UserAdapter class UserAdapter(val users: List<User>): RecyclerView.Adapter<ViewHolder>() { override fun onCreateViewHolder(parent:

    ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.user.set(users[position]) } }
  17. UserAdapter class UserAdapter(val users: List<User>): RecyclerView.Adapter<ViewHolder>() { override fun onCreateViewHolder(parent:

    ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.user.set(users[position]) } } UserListItemBinding༻
 ViewHolder
  18. UserAdapter class UserAdapter(val users: List<User>): RecyclerView.Adapter<ViewHolder>() { override fun onCreateViewHolder(parent:

    ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.user.set(users[position]) } } onBindViewHolderͰ
 ϢʔβʔΛηοτ͢Δ
  19. ϢʔβʔϦετΛ
 APIͰऔಘ͢Δ৔߹͸ʁ

  20. UserListViewModel class UserListViewModel(...): BaseObservable() { val users = mutableListOf<User>() fun

    onStart() { // getUsers͸Single<List<User>> getUsers().subscribe({ users.addAll(it) adapter.notifyDataSetChanged() }) } }
  21. UserListViewModel class UserListViewModel(...): BaseObservable() { val users = mutableListOf<User>() fun

    onStart() { // getUsers͸Single<List<User>> getUsers().subscribe({ users.addAll(it) adapter.notifyDataSetChanged() }) } } ???
  22. Ϧετͷมߋ௨஌ • ϏϡʔϞσϧ͕adapterΛ࣋ͭͷ͕ؾ࣋ͪѱ͍ • ObservableInt΍ObservableFieldΈ͍ͨͳ
 ௨஌ͷ࢓૊Έ͕ཉ͍͠ • ஋Ληοτ͢Δ͚ͩͰ௨஌͞Εͯ΄͍͠

  23. ObservableList • android.databindingύοέʔδ • ௨஌ػೳͷ͋ΔϦετ • ObservableArrayListͰΠϯελϯεԽ

  24. UserListViewModel class UserListViewModel: BaseObservable() { val users = ObservableArrayList<User>() //

    Called from activity's onCreate fun initialize() { getUsers().subscribe({ users.addAll(it) }) } }
  25. UserListViewModel class UserListViewModel: BaseObservable() { val users = ObservableArrayList<User>() //

    Called from activity's onCreate fun initialize() { getUsers().subscribe({ users.addAll(it) }) } } ObservableList
  26. UserListViewModel class UserListViewModel: BaseObservable() { val users = ObservableArrayList<User>() //

    Called from activity's onCreate fun initialize() { getUsers().subscribe({ users.addAll(it) }) } } ͜Ε͚ͩͰOK
  27. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init { users.addOnListChangedCallback(object:

    ObservableList.OnListChangedCallback<ObservableList<User>>() { override fun onChanged(users: ObservableList<User>?) { notifyDataSetChanged() } ... }) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {...} override fun onBindViewHolder(holder: ViewHolder, position: Int) {...} }
  28. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init { users.addOnListChangedCallback(object:

    ObservableList.OnListChangedCallback<ObservableList<User>>() { override fun onChanged(users: ObservableList<User>?) { notifyDataSetChanged() } ... }) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {...} override fun onBindViewHolder(holder: ViewHolder, position: Int) {...} } ίϯετϥΫλͰObservableListΛड͚औΔ
  29. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init { users.addOnListChangedCallback(object:

    ObservableList.OnListChangedCallback<ObservableList<User>>() { override fun onChanged(users: ObservableList<User>?) { notifyDataSetChanged() } ... }) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {...} override fun onBindViewHolder(holder: ViewHolder, position: Int) {...} } ॳظԽ࣌ʹ ίʔϧόοΫొ࿥
  30. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init { users.addOnListChangedCallback(object:

    ObservableList.OnListChangedCallback<ObservableList<User>>() { override fun onChanged(users: ObservableList<User>?) { notifyDataSetChanged() } ... }) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {...} override fun onBindViewHolder(holder: ViewHolder, position: Int) {...} } ֤ίʔϧόοΫͰ
 notifyʙΛݺͿ
  31. ༨ஊ: ϕʔεΫϥεʹ͢Δ abstract class ObservableRecyclerAdapter<T>( val items: ObservableList<T> ): RecyclerView.Adapter<BindingViewHolder>()

    { init { items.addOnListChangedCallback(object: ObservableList.OnListChangedCallback<ObservableList<T>>() { override fun onChanged(items: ObservableList<T>?) { notifyDataSetChanged() } ... }) } }
  32. ༨ஊ: ϕʔεΫϥεʹ͢Δ abstract class ObservableRecyclerAdapter<T>( val items: ObservableList<T> ): RecyclerView.Adapter<BindingViewHolder>()

    { init { items.addOnListChangedCallback(object: ObservableList.OnListChangedCallback<ObservableList<T>>() { override fun onChanged(items: ObservableList<T>?) { notifyDataSetChanged() } ... }) } }
  33. ͜ΕͰϦετΛૢ࡞͢Δ͚ͩͰ
 ը໘ʹ൓ө͞ΕΔΑ͏ʹͳͬͨʂ

  34. ͳΜ͔ͪΒͭ͘...

  35. ͳͥʁ • όΠϯυର৅ͷΦϒδΣΫτͷมߋͷ
 ࣍ͷϑϨʔϜͰUI͕ߋ৽͞ΕΔ • SwipeRefreshLayoutͱͷ૊Έ߹ΘͤͰݦஶ • ͢ͰʹϏϡʔ͕࡞੒ࡁΈͷঢ়ଶͰɺ
 clear +

    addAll
  36. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init {...} override

    fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder { ... } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.user.set(users[position]) binding.executePendingBindings() } }
  37. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init {...} override

    fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder { ... } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.user.set(users[position]) binding.executePendingBindings() } } ͜ΕͰଈ࣌ʹUIߋ৽͞ΕΔʂ
  38. ϦετͷΞΠςϜ಺ͷ
 Πϕϯτ

  39. ྫ • ֤ΞΠςϜͷը૾ΛλοϓͰ֦େද͍ࣔͨ͠ • ͦΕҎ֎ͷ෦෼ΛλοϓͰɺৄࡉϓϩϑΟʔ ϧΛද͍ࣔͨ͠ • ListViewͳΒҎԼͰ΋OK
 android:onItemClick=“@{viewModel::onItemClick}”

  40. ΫϦοΫͰ֦େ

  41. ΫϦοΫͰৄࡉ΁

  42. Files • ը໘શମ • user_list_activity.xml • UserListActivity • UserAdapter •

    UserListViewModel • ֤ΞΠςϜ • user_list_item.xml • UserViewModel ʢ֤ΞΠςϜͷϏϡʔϞσϧʣ
  43. user_list_item.xml <layout> <data> <variable name="viewModel" type="com.example.app.UserViewModel"/> </data> <LinearLayout android:onClick="@{viewModel::onItemClick}"> <ImageView

    app:imageUrl="@{viewModel.user.imageUrl}" android:onClick="@{viewModel::onImageClick}"/> <TextView android:text="@{viewModel.user.name}"/> </LinearLayout> </layout>
  44. user_list_item.xml <layout> <data> <variable name="viewModel" type="com.example.app.UserViewModel"/> </data> <LinearLayout android:onClick="@{viewModel::onItemClick}"> <ImageView

    app:imageUrl="@{viewModel.user.imageUrl}" android:onClick="@{viewModel::onImageClick}"/> <TextView android:text="@{viewModel.user.name}"/> </LinearLayout> </layout> ΞΠςϜ͝ͱͷ
 ϏϡʔϞσϧ
  45. user_list_item.xml <layout> <data> <variable name="viewModel" type="com.example.app.UserViewModel"/> </data> <LinearLayout android:onClick="@{viewModel::onItemClick}"> <ImageView

    app:imageUrl="@{viewModel.user.imageUrl}" android:onClick="@{viewModel::onImageClick}"/> <TextView android:text="@{viewModel.user.name}"/> </LinearLayout> </layout> ΫϦοΫΠϕϯτΛ
 όΠϯυ
  46. UserViewModel class UserViewModel: BaseObservable() { val user = ObservableField<User>() fun

    onItemClick(view: View) { // go to profile } fun onImageClick(view: View) { // go to image viewer } }
  47. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init {...} override

    fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) binding.viewModel = UserViewModel() return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.viewModel.user.set(users[position]) binding.executePendingBindings() } }
  48. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init {...} override

    fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) binding.viewModel = UserViewModel() return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.viewModel.user.set(users[position]) binding.executePendingBindings() } } Ϗϡʔͷ࡞੒࣌ʹ
 ϏϡʔϞσϧΛηοτ
  49. UserAdapter class UserAdapter(val users: ObservableList<User>): RecyclerView.Adapter<ViewHolder>() { init {...} override

    fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = UserListItemBinding.inflate(inflater, parent, false) binding.viewModel = UserViewModel() return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = holder.binding binding.viewModel.user.set(users[position]) binding.executePendingBindings() } } ϏϡʔϞσϧͷ
 ϢʔβʔΛߋ৽
  50. ·ͱΊ • σʔλόΠϯσΟϯάΛRecyclerViewͰ࢖͏ ํ๏ͷ঺հ • ObservableList • executePendingBindings • ΞΠςϜ͝ͱʹϏϡʔϞσϧ

  51. Thanks!