提问人:JSONParser 提问时间:2/28/2023 最后编辑:JSONParser 更新时间:3/19/2023 访问量:149
从回调 Kotlin 中获取价值
getting value from callback kotlin
问:
尝试制作一个文件 downloadManager
我们有一个包含 Recycler 视图的活动,Recycler 视图中的每个项目都代表一个处于下载、下载状态的文件。每个回收器视图项都有一个回调,此回调有 3 个信息:onSuccess (file)、onError(Error)、progress(Int)。 现在我想在 BindViewHolder 中提取此信息以显示进度,但我无法在回调中获取值: (为简单起见,删除其他代码)
class DownloadActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val list = mutableListOf<DItem>()
list.add(DItem("url", callback = object : Listener{
override fun onSuccess(file: File) {
}
override fun onFailure(error: Error) {
}
override fun onProgress(progress: Int) {
}
})
// trigger from here for simplicity otherwise each list item has a download button which will trigger this:
FileDownloadManager().download("utl", list[0].callback)
}
// adapter
class DownloadAdapter : RecyclerView.Adapter<MyViewhOdler>() {
val list = mutableListOf<DItem>()
override fun onBindViewHolder(holder: MyViewhOdler, position: Int) {
// how to get value here:
list.get(0).callback
}
}
class FileDownloadManager {
override fun download(url: String, callback: Listener) {
// on donwloading start, will trigger
// callback.progress(<some value>)
}
interface Listener{
fun onSuccess(file: File)
fun onFailure(error: Error)
fun onProgress(progress: Int)
}
}
// Ditem
data class DItem (
var url: String? = null,
var callback: Listener,
var fcallback: ((File, Error, Int)-> Unit)
)
}
答:
如果我理解正确,您想在“onBindViewHolder()”中获取“progress”值,但您不知道该怎么做。
我首先想到的一件事,不是修改大部分代码,但也可能是一个肮脏的解决方案,是:
您稍后实际上定义了对象回调,因此构造函数将不再接受“callback”,而是稍后将初始化的 var。
class DItem(
var url: String? = null,
var fcallback: ((File, Error, Int) -> Unit)
) {
lateinit var callback: FileDownloadManager.Listener
}
此时,在“onBindViewHolder()”中,您现在可以定义回调并在该位置获取值:
fun onBindViewHolder() {
println("onBindViewHolder")
list[0].callback = object : FileDownloadManager.Listener {
override fun onSuccess(file: File) {
}
override fun onFailure(error: Error) {
}
override fun onProgress(progress: Int) {
print("progress: $progress")
}
}
}
我希望我确实正确地理解了这个问题,我真的想强调这样一个事实,即这不一定是一个干净的解决方案,而是实现速度最快且代码重构量最少的解决方案之一。
评论
我认为您的问题源于这样一个事实,即您的适配器中有一个具有复杂行为的域模型列表,其中应该是非常愚蠢的视图模型,仅表示每个列表项的当前状态。
onBindViewHolder
只是为了将给定位置的项目的当前状态拍打到同一位置的匹配视图。它不应该保留回调或尝试更新自己。
您可以尝试将域模型包装在一个对象中,该对象保持当前的进度状态,然后通知所属适配器是时候刷新了。
例如:
这是适配器中的项目。 它将包装数据模型并公开当前状态以绑定到视图。
class ListItem(val url : String) {
val currentProgress = MutableLiveData<Int>(0)
val dItem = DItem(url, object : callback {
fun onProgress(int progress) {
currentProgress.postValue(progress)
}
// ...
// Store file or error from other functions as well
}
}
然后,您的活动会创建这些对象(而不是 DItem)的列表,观察状态更改,并通知适配器该索引在更改时需要刷新:
class DownloadActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val list = mutableListOf<ListItem>()
list.add(ListItem("url").apply {
currentProgress.observe(this@DownloadActivity) {
// Simple implementation just refreshes the whole list when one progress changes
// Exercise for the reader to pass along the specific index to mark as change
adapter.notifyDataChanged()
}
})
然后,ViewHolder 只关心委派按钮单击事件并将视图设置为当前状态:
override fun onBindViewHolder(holder: MyViewhOdler, position: Int) {
val listItem = list.get(position)
holder.buttonThatTriggersDownload.setOnClickListener {
// Set click listener to trigger download
}
holder.viewThatShowsDownloadProgress.value = listItem.currentProgress.value
}
评论
DItem
callback