This is an EXTRA CREDIT exercise, so complete it if you’re up for a challenge!
In this exercise you’ll add a header to your RecyclerView. It has lots of steps, but when you’re done, your app will display a header as the first row of the list.
Let’s finish the adapter using DataItems. You can use this more advanced pattern when you have more than two types of views to hold in a RecyclerView.
At the bottom of SleepNightAdapter, add a sealed class called DataItem:
sealed class DataItem {
data class SleepNightItem(val sleepNight: SleepNight): DataItem() {
override val id = sleepNight.nightId
}
object Header: DataItem() {
override val id = Long.MIN_VALUE
}
abstract val id: Long
}
Add the TextHolder class inside the SleepNightAdapter class.
class TextViewHolder(view: View): RecyclerView.ViewHolder(view) {
companion object {
fun from(parent: ViewGroup): TextViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.header, parent, false)
return TextViewHolder(view)
}
}
}
Update the declaration of SleepNightAdapter to support any type of view holder.
class SleepNightAdapter:
ListAdapter<SleepNight, RecyclerView.ViewHolder>(SleepNightDiffCallback())
Now let’s update ListAdapter to hold a list of DataItem instead of a list of SleepNight:
class SleepNightAdapter:
ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()) {}
Update your DiffCallback to handle DataItem instead of SleepNight:
class SleepNightDiffCallback : DiffUtil.ItemCallback<DataItem>() {
override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem == newItem
}
}
Then, to figure out what view type to return, add a check to see which type of item is in the list:
At the top of the file, before the class declaration, create variables for Header and SleepNight item types:
private val ITEM_VIEW_TYPE_HEADER = 0
private val ITEM_VIEW_TYPE_ITEM = 1
Then override getItemViewType and return the correct item view type.
override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
}
}
Change onCreateViewHolder’s return type to RecyclerView.ViewHolder, and update it to return the correct ITEM_VIEW_TYPE.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ITEM_VIEW_TYPE_HEADER -> TextViewHolder.from(parent)
ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
else -> throw ClassCastException("Unknown viewType ${viewType}")
}
}
In onBindViewHolder() you’ll need to unwrap the DataItem to pass a SleepNight to the ViewHolder
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is ViewHolder -> {
val nightItem = getItem(position) as DataItem.SleepNightItem
holder.bind(nightItem.sleepNight, clickListener)
}
}
}
You’ll need a way to convert a List to a List.
private val adapterScope = CoroutineScope(Dispatchers.Default)
fun addHeaderAndSubmitList(list: List<SleepNight>?) {
adapterScope.launch {
val items = when (list) {
null -> listOf(DataItem.Header)
else -> listOf(DataItem.Header) + list.map DataItem.SleepNightItem(it)
}
}
withContext(Dispatchers.Main) {
submitList(items)
}
}
}
Finally, update SleepTrackerFragment to pass a list of DataItem instead of a list of SleepNight and call the new addHeaderAndSubmitList method instead of submitList method:
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.addHeaderAndSubmitList(it)
}
})
If you want to start at this step, you can download this exercise from: Step.13-Exercise-Add-a-List-Header.
You will find plenty of //TODO comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here: Step.13-Solution-Add-a-List-Header, or using this git diff.
转载:https://learn.udacity.com/courses/ud9012/lessons/97c42668-51b8-454c-ba29-5ddfd2b92f6b/concepts/4392f247-36a7-42bb-9989-6957b795108c?lesson_tab=lesson