我在android中有一个回收站视图适配器。我的适配器类的一部分看起来像这样:
private lateinit var itemLongClick: ItemLongClick
override fun onCreateViewHolder(parent: ViewGroup, a: Int): RecyclerAdapter.ViewHolder {
// Define And Initialize The Custom View And Its Holder//
val myView = LayoutInflater.from(parent.context).inflate(customLayout, parent, false)
val viewHolder = ViewHolder(myView)
// What Happens When A List Item Is Long Clicked//
myView.setOnLongClickListener { view ->
// Differ Action To Class Instance//
itemLongClick.longClicked(context, viewHolder.layoutPosition, view)
// End Function//
true
}
// Returns The Custom View//
return viewHolder
}
fun setItemLongClick(itemLongClick: ItemLongClick) {
// Sets The Value For this.itemLongClick//
this.itemLongClick = itemLongClick
}
我创建的界面如下:
interface ItemLongClick {
// Function Declaration For When An Item Is Long Clicked//
fun longClicked(context: Context, position: Int, view: View)
}
我不想将我的长按代码写在适配器类中,而是希望将其与调用适配器类的活动区分开。我知道这样做的一种方法是创建一个kotlin接口,然后在另一个这样的类中调用它
userAdapter.setItemLongClick(object: ItemLongClick {
override fun longClicked(context: Context, position: Int, view: View) {
}
})
但这看起来很混乱。我知道Java接口可与SAM一起使用,但我也不想这样做。我想要的是让onLongClick成为Lambda,但我不确定如何设置Kotlin lambda表达式来实现此功能,而且我在任何地方都找不到很好的示例。
预先感谢
答案 0 :(得分:5)
您有两个选择:
1。)用typealias替换接口
typealias ItemLongClick = (Context, Int, View) -> Unit
2。)添加扩展功能,用于将接口设置为lambda而不是匿名对象
inline fun UserAdapter.setItemLongClick(crossinline longClick: (Context, Int, View) -> Unit) {
setItemLongClick(object: ItemLongClick {
override fun longClicked(context: Context, position: Int, view: View) {
longClick(context, position, view)
}
})
}
现在您可以打电话
userAdapter.setItemLongClick { context, position, view ->
...
}
答案 1 :(得分:1)
我有一个适配器,我需要根据开关来更改数据,并且我做了类似的事情:
ListAdapter(private val context: Context, private val switchListener: (Boolean) -> Unit)
然后将绑定的节的标题绑定到哪里:
private fun bindHeader(holder: HeaderViewHolder) {
holder.switch.setOnCheckedChangeListener { _, isChecked ->
callbackSwitchListener(isChecked)
}
}
在我的片段中:
private fun setupRecyclerView() {
fabricationDataListAdapter =
FabricationDataListAdapter(context!!) { isChecked: Boolean -> switchControl(isChecked) }
val layoutManager = ListLayoutManager(context!!)
this.recycler_view_all.layoutManager = layoutManager
this.recycler_view_all.adapter = fabricationDataListAdapter
}
有趣的switchControl在其中根据布尔值更改了数据。
我不确定这是否是您所需要的,我有点着急,但是如果我没记错的话,这在kotlin中被称为高阶函数。
答案 2 :(得分:0)
在下面的代码中,我使用可过滤适配器在列表上进行搜索。在这里,我使用 lambda 作为回调,以在未找到搜索数据时通知查看模型。
在ViewModel中实例化适配器。并传递lambda
var matterAdapter = MatterAdapter(matterList) {
//todo - got callback
}
适配器
class MatterAdapter (var filteredList : MutableList<AndroidViewModel>, val funcNoSearchData : () -> Unit) : DataBindingRecyclerViewAdapter(filteredList), Filterable {
private var mViewModelMap: MutableMap<Class<*>, Int> = mutableMapOf()
private var originalList : MutableList<AndroidViewModel> = mutableListOf()
private val mFilter = ItemFilter()
init {
mViewModelMap.put(MatterRowViewModel::class.java, R.layout.row_matter)
}
override fun getViewModelLayoutMap(): MutableMap<Class<*>, Int> {
return mViewModelMap
}
override fun getFilter(): Filter {
return mFilter
}
private inner class ItemFilter : Filter() {
override fun performFiltering(constraint: CharSequence): FilterResults {
val filterString = constraint.toString().toLowerCase()
val results = FilterResults()
val list = originalList
val count = list.size
val nlist = ArrayList<AndroidViewModel>(count)
var filterableString: String
for (i in 0 until count) {
filterableString = (list.get(i) as MatterRowViewModel).matter.casestitle!!
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(list.get(i))
}
}
results.values = nlist
results.count = nlist.size
return results
}
override fun publishResults(constraint: CharSequence, results: Filter.FilterResults) {
filteredList.clear()
filteredList.addAll(results.values as ArrayList<AndroidViewModel>)
// sends empty search callback to viewmodel
if(filteredList.size == 0) {
funcNoSearchData()
}
notifyDataSetChanged()
}
}
fun resetSearch() {
filteredList.clear()
filteredList.addAll(originalList)
notifyDataSetChanged()
}
fun refreshData() {
originalList = ArrayList(filteredList)
notifyDataSetChanged()
}
}
答案 3 :(得分:0)
Kotlin 1.4发行版的Kotlin documentation指出:
在Kotlin 1.4.0之前,仅当使用Kotlin的Java方法和Java接口时,才能应用SAM(单一抽象方法)转换。从现在开始,您还可以将SAM转换用于Kotlin接口。为此,请使用fun修饰符将Kotlin界面明确标记为可以正常工作。
fun interface Operation1 {
operator fun invoke(x: String): String
}
fun interface Operation2 {
fun doSomething(x: Int): String
}
val operation1 = Operation1 { "$it world!" }
val operation2 = Operation2 { "$it world!" }
fun main() {
// Usage: First sample.
println(operation1("Hello"))
println(operation2.doSomething(0))
// Usage: Second sample.
println(Operation1 { "$it world!" }("Hello"))
println(Operation2 { "$it!" }.doSomething(0))
}
您可以阅读有关功能接口here的更多信息。