我有一个适配器,其中每个项都有3个按钮,它们会生成一个对话框,然后执行一个动作。我感觉应该从适配器中删除它(我有可用的视图模型),但是它起作用了,我在想:我是否应该将逻辑移到片段,视图模型,是否需要全部移走(下面的代码是不好的做法,如果是,为什么呢?任何帮助/输入将不胜感激。
这是适配器代码:
class ViewRecipesAdapter(val context: Context, private val recipes: List<Recipe>, private val parentFragment: Fragment) :
RecyclerView.Adapter<ViewRecipesAdapter.RecipeViewHolder>()
{
private var listToUse: List<Recipe> = recipes
private lateinit var recipesViewModel: RecipesViewModel
private var isView = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder
{
val layoutInflater = LayoutInflater.from(parent.context)
val binding: ViewRecipesItemBinding =
DataBindingUtil.inflate(layoutInflater, R.layout.view_recipes_item, parent, false)
return RecipeViewHolder(binding, context)
}
override fun getItemCount() = listToUse.size
override fun onBindViewHolder(holder: RecipeViewHolder, position: Int)
{
val recipe = listToUse[position]
// to delete and edit items
val dao = RecipesDatabase.getInstance(context).recipeDao()
val repository = RecipeRepository(dao)
recipesViewModel = RecipesViewModel(repository)
//display data on list item
holder.bind(recipe)
Glide.with(context).load(recipe.imageOne)
.into(holder.binding.imageViewItemImage)
//tried to handle clicks here through the viewModel but I could not get it working from fragment
//the function call after viewModel calls is what works and it seems to work well
holder.binding.imageButtonItemdelete.setOnClickListener {
recipesViewModel.setIsDelete(true)
recipesViewModel.setPositionFromAdapter(position)
startDeleteDialog(position)
}
holder.binding.imageButtonItemedit.setOnClickListener {
recipesViewModel.setIsView(false)
recipesViewModel.setPositionFromAdapter(position)
isView = false
startEditOrViewDialog(position)
}
holder.binding.imageButtonItemview.setOnClickListener {
recipesViewModel.setIsView(true)
recipesViewModel.setPositionFromAdapter(position)
isView = true
startEditOrViewDialog(position)
}
}
fun setList(newList: List<Recipe>)
{
listToUse = newList
}
//dialog functions for the edit, delete, and view buttons on each item
private fun startDeleteDialog(position: Int)
{
AlertDialog.Builder(context)
.setTitle("Delete recipe?")
.setPositiveButton("Yes") { _, _ ->
recipesViewModel.deleteRecipe(recipes[position])
notifyItemRemoved(position)
}
.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}.show()
}
private fun startEditOrViewDialog(position: Int)
{
when (isView)
{
true ->
{
AlertDialog.Builder(context).setTitle("View recipe?")
.setPositiveButton("Yes") { _, _ ->
//get relevant data from current recipe
val recipe = recipes[position]
//create a dialog that shows this data in an inflated layout
val viewDialog = AlertDialog.Builder(context)
val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.fragment_edit_or_view, null)
view.editText_editrecipe_directions.setText(recipe.directions)
view.editText_editrecipe_ingredients.setText(recipe.ingredients)
view.editText_editrecipe_notes.setText(recipe.notes)
view.editText_editrecipe_title.setText(recipe.title)
view.textView_date_edit.text = recipe.date
view.editText_editrecipe_title.keyListener = null
view.editText_editrecipe_directions.keyListener = null
view.editText_editrecipe_ingredients.keyListener = null
view.editText_editrecipe_notes.keyListener = null
if (recipe.rating != null)
{
view.ratingBar_edit.rating = recipe.rating
}
Glide.with(context)
.load(recipe.imageOne)
.into(view.imageView_addphoto_edit)
viewDialog.setView(view).show()
}
.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}.show()
}
false ->
{
AlertDialog.Builder(context).setTitle("Edit recipe?")
.setPositiveButton("Yes") { _, _ ->
//get relevant data from current recipe
val recipe = recipes[position]
val idString = recipe.id.toString()
recipesViewModel.setId(idString)
recipesViewModel.getRecipeById2(idString)
notifyDataSetChanged()
val controller = parentFragment.findNavController()
controller.navigate(
ViewRecipesFragmentDirections.actionNavViewrecipesToNavAddrecipe(
recipe.id.toString()
)
)
}
.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}.show()
}
}
}
override fun getItemId(position: Int): Long
{
return position.toLong()
}
override fun getItemViewType(position: Int): Int
{
return position
}
class RecipeViewHolder(val binding: ViewRecipesItemBinding, val context: Context) :
RecyclerView.ViewHolder(binding.root)
{
fun bind(recipe: Recipe)
{
if (recipe.isLeftover == true)
{
binding.tvIsLeftovers.visibility = View.VISIBLE
}
binding.textViewItemTitle.text = recipe.title
if (recipe.date != null)
{
binding.textViewItemDate.text = recipe.date
}
if (recipe.rating != null)
{
binding.ratingBar2.rating = recipe.rating
}
binding.root.animation = AlphaAnimation(0.0f, 1.0f).apply {
duration = 1000
}
}
}
}
这是视图模型,设置了实时数据变量,使我无法使用此RecyclerView所在的片段:
class RecipesViewModel(private val repository: RecipeRepository) : ViewModel()
{
val recipesList = repository.getAllRecipes()
private val _isView = MutableLiveData<Boolean>()
val isView: MutableLiveData<Boolean> = _isView
private val _isEdit = MutableLiveData<Boolean>()
val isEdit: MutableLiveData<Boolean> = _isEdit
private val _positionFromAdapter = MutableLiveData<Int>()
val positionFromAdapter: MutableLiveData<Int> = _positionFromAdapter
private val _isDelete = MutableLiveData<Boolean>()
val isDelete: MutableLiveData<Boolean> = _isDelete
private val _recipesListFromSearch = MutableLiveData<List<Recipe>>()
val recipesListFromSearch: LiveData<List<Recipe>> = _recipesListFromSearch
private val _recipe = MutableLiveData<Recipe>()
val recipe: LiveData<Recipe> = _recipe
lateinit var searchString: String
val savedId = MutableLiveData<String>()
fun setPositionFromAdapter(position: Int)
{
_positionFromAdapter.value = position
}
fun setIsView(isView: Boolean)
{
_isView.value = isView
}
fun setIsDelete(isDelete: Boolean)
{
_isView.value = isDelete
}
fun setIsEdit(isEdit: Boolean)
{
_isEdit.value = isEdit
}
fun setId(id: String)
{
savedId.value = id
}
fun insertRecipe(recipe: Recipe)
{
CoroutineScope(Dispatchers.IO).launch {
repository.insertRecipe(recipe)
}
}
fun getRecipesFromQuery(query: String)
{
CoroutineScope(Dispatchers.IO).launch {
val list = repository.getRecipesSearch(query)
MainScope().launch { _recipesListFromSearch.value = list }
}
}
fun saveUserRecipeToDb(
title: String?,
ingredients: String?,
directions: String?,
notes: String?,
uriToSave: String?,
rating: Float?,
date: String?,
isLeftover: Boolean,
loadedId: String
): Boolean
{
val recipeToSave = Recipe(
title,
ingredients,
directions,
notes,
uriToSave,
null,
null,
rating,
date,
isLeftover
)
if (loadedId != "666")
{
recipeToSave.id = loadedId.toInt()
}
insertRecipe(recipeToSave)
return false
}
fun getRecipeById2(id: String) = repository.getRecipeByIdLive(id)
fun deleteRecipe(recipe: Recipe)
{
CoroutineScope(Dispatchers.IO).launch {
repository.deleteRecipe(recipe)
}
}
}
如何onClick
在RecyclerView中实施。假设在“回收站”中,每个视图都是某些视图的可视化,item
并且当您单击该视图时,您想要对该项目执行某些操作:
ClickListener
::class ClickListener(
val clickListener: (itemId: Int) -> Unit,
)
{
fun onClick(item: ItemClass) = clickListener(item.id)
}
class RecylerViewAdapter(
private val clickListener: ClickListener
)
onBindViewHolder
通过这Listenner作为参数override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
holder.bind(getItem(position)!!, clickListener)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
{
return ViewHolder.from(
parent
)
}
class ViewHolder private constructor(private val binding: ItemRecyclerBinding) :
RecyclerView.ViewHolder(binding.root)
{
companion object
{
fun from(parent: ViewGroup): ViewHolder
{
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemRecyclerBinding.inflate(layoutInflater, parent, false)
return ViewHolder(
binding
)
}
}
fun bind(
item : Item,
clickListener: ClickListener
)
{
binding.item = item
binding.clickListener = clickListener
binding.executePendingBindings()
}
}
<data>
<variable
name="item"
type="com.example.sth.database.Item" /> // path to `Item`
<variable
name="clickListener"
type="com.example.sth.ui.adapter.ClickListener" /> // Path to `ClickListener`
</data>
onClick
向Button添加方法:android:onClick="@{() -> clickListener.onClick(item)}"
clickListenner
作为参数传递。这样,您可以处理片段中的所有内容,而RecyclerView并不关心您在此功能中所做的事情。val clickListenner = ClickListenner(
{ id -> viewModel.clickItemWithid(id) }, // click. This function from ViewModel will be executed when You click on item in recycler View
)
val adapter = RecylerViewAdapter (
clickListenner
)
此方法基于Udacity上的Google开发人员代码实验室。
在这里您可以检查整个代码实验室。它是免费的。
这只是一个实现点击监听器的视频
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句