从回调Kotlin获取值

cpjpxq1n  于 2023-03-19  发布在  Kotlin
关注(0)|答案(2)|浏览(288)

bounty将在3天后过期。回答此问题可获得+50的声誉奖励。JSONParser正在寻找来自声誉良好来源的答案

尝试将文件downloadManager
我们有一个包含回收器视图的活动,回收器视图中的每个项目代表一个处于下载或已下载状态的文件。每个回收器视图项目都有一个回调函数,该回调函数包含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)

)

    }
kcwpcxri

kcwpcxri1#

如果我理解正确的话,您希望在“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")
        }
    }
}

我希望我正确地理解了这个问题,我真的想强调一个事实,这不一定是一个干净的解决方案,但最快的实现和最少的代码重构量之一。

krcsximq

krcsximq2#

我认为您的问题源于这样一个事实,即您在适配器中有一个具有复杂行为的 * 域 * 模型列表,其中应该是真正愚蠢的 * 视图 * 模型,它们只表示每个列表项的当前状态。
onBindViewHolder的作用只是将给定位置项的当前状态传递给相同位置的匹配视图,而不应该保留回调或尝试更新自身。
您可以尝试将您的域模型 Package 在一个对象中,该对象维护当前的进度状态,然后通知拥有它的适配器该刷新了。
例如:
这是将在适配器中的项。它将 Package 数据模型并公开绑定到视图的当前状态。

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
    }
 }

然后,您的Activity创建这些对象的列表,而不是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
}

相关问题