ViewModel
ViewModelは前回の記事でも登場しましたが、アクティビティに必要なデータを保持するクラスです。
この中でDBのデータをRepository経由で取り出してリストに詰めて持っておきたいと思うのですが、今回は記事が長くなりそうなので一旦固定値のvisitedRestaurantListを持たておきます。
class VisitedRestaurantViewModel(application: Application): AndroidViewModel(application) {
val visitedRestaurantList = listOf(
VisitedRestaurantListItem("吉野家",Evaluation.THREE_STAR,"東京","和食","2023/11/01","新メニューが美味しかった",
ContextCompat.getDrawable(application, R.drawable.gyudon),true),
VisitedRestaurantListItem("サイゼリヤ",Evaluation.FIVE_STAR,"名古屋","イタリアン","2023/11/01","安すぎ",ContextCompat.getDrawable(application, R.drawable.doria),true),
VisitedRestaurantListItem("牛角",Evaluation.FOUR_STAR,"大阪","焼肉","2023/11/01","牛タンうまい",ContextCompat.getDrawable(application, R.drawable.yakiniku),false),
VisitedRestaurantListItem("CoCo壱",Evaluation.THREE_STAR,"京都","カレー","2023/11/01","辛かった",ContextCompat.getDrawable(application, R.drawable.curry),true),
VisitedRestaurantListItem("天下一品",Evaluation.ONE_STAR,"神戸","ラーメン","2023/11/01","味が濃い",ContextCompat.getDrawable(application, R.drawable.ramen),false),
VisitedRestaurantListItem("コメダ珈琲",Evaluation.TWO_STAR,"広島","カフェ","2023/11/01","量多い",ContextCompat.getDrawable(application, R.drawable.komeda),false),
VisitedRestaurantListItem("スシロー",Evaluation.THREE_STAR,"沖縄","寿司","2023/11/01","サーモン3皿食べた",ContextCompat.getDrawable(application, R.drawable.sushiro),true),
VisitedRestaurantListItem("餃子の王将",Evaluation.FIVE_STAR,"札幌","中華","2023/11/01","餃子テイクアウトした",ContextCompat.getDrawable(application, R.drawable.gyoza),false),
VisitedRestaurantListItem("やよい軒",Evaluation.THREE_STAR,"仙台","和食","2023/11/01","健康的",ContextCompat.getDrawable(application, R.drawable.yayoi),true),
VisitedRestaurantListItem("マクドナルド",Evaluation.FOUR_STAR,"青森","ファストフード","2023/11/01","ポテト高くなってた",ContextCompat.getDrawable(application, R.drawable.mac),false)
)
}
Adapter
Adapterの実装も修正します。
以前RecyclerViewを実装した時はRecyclerView.Adapterを継承していたのですが、今回はListAdapterを採用してみます。
ListAdapter は RecyclerView.Adapterを継承したクラスです。
RecyclerView.Adapterと異なりoverrideする関数が少なくリスト変数を保持する必要がないListAdapterを継承するのが一般的なようです。
VisitedRestaurantListItemBindingでvisited_restaurant_list_item.xmlに持たせたvisitedRestaurantItem変数に情報を渡すbind()を作り、onBindViewHolderの中で実行しています。
class VisitedRestaurantListAdapter(private val viewModel: VisitedRestaurantViewModel): ListAdapter<VisitedRestaurantListItem, VisitedRestaurantListAdapter.VisitedRestaurantCardViewHolder>(DiffCallBack) {
class VisitedRestaurantCardViewHolder(private val binding: VisitedRestaurantListItemBinding): RecyclerView.ViewHolder(binding.root) {
fun bind(item: VisitedRestaurantListItem) {
binding.visitedRestaurantItem = item
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VisitedRestaurantCardViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return VisitedRestaurantCardViewHolder(VisitedRestaurantListItemBinding.inflate(layoutInflater,parent,false))
}
override fun getItemCount(): Int {
return viewModel.visitedRestaurantList.count()
}
override fun onBindViewHolder(holder: VisitedRestaurantCardViewHolder, position: Int) {
holder.bind(viewModel.visitedRestaurantList[position])
}
}
ListAdapterではDiffUtil.ItemCallback型の変数をコンストラクタに渡す必要があるので、Adapterクラス内で定義しておきます。
これは2つの要素を比較するユーティリティクラスで、ListAdapterでは要素の追加・変更・削除を検知するのに使われます。
これで判定基準が適切かはさておき、ひとまず必要なので作成しておきました。
private object DiffCallBack: DiffUtil.ItemCallback<VisitedRestaurantListItem>() {
override fun areContentsTheSame(
oldItem: VisitedRestaurantListItem,
newItem: VisitedRestaurantListItem
): Boolean {
return oldItem == newItem
}
override fun areItemsTheSame(
oldItem: VisitedRestaurantListItem,
newItem: VisitedRestaurantListItem
): Boolean {
return oldItem.restaurantName == newItem.restaurantName
}
}