从广播接收器更新Recyclerview中的进度栏

时间:2019-04-15 02:40:02

标签: android kotlin android-recyclerview android-progressbar

我正试图弄清楚如何从接收方收到进度更新后更新特定项目的进度栏。

这是我的收件人片段:

private val mReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when(intent.action) {
                PROGRESS_UPDATE_ACTION -> {
                    val resId = intent.extras.getInt("resourceID")
                    val progress = intent.extras.getInt("contentLength$resId")
                    val maxProgress = intent.extras.getLong("maxProgress$resId")
                    adapter.update(resId, progress, maxProgress)
                }
            }
        }
    }

适配器是从数据库填充的。每个项目都有一个唯一的resourceID。

private fun loadDataFromBox(){
        val query = SaveOfflineManager().getAll()
        val saveOfflineData = LinkedHashMap<Int, SaveOfflineData>()
        query.forEach {
            saveOfflineData[it.resourceID!!] = it
        }

        adapter.setData(saveOfflineData)
        adapter.notifyDataSetChanged()
    }

这是我的简化适配器。如您所见,我不知道如何处理从接收方接收更新的方法。我尝试搜索解决方案数小时,但似乎找不到任何解决方案。

class SaveOfflineAdapter : RecyclerView.Adapter<SaveOfflineAdapter.SimpleViewHolder>() {

    private var downloadMap : LinkedHashMap<Int, SaveOfflineData> = LinkedHashMap()
    private var utils : Utils = Utils()


    fun setData(downloadist : LinkedHashMap<Int, SaveOfflineData>) {
        this.downloadMap.clear()
        this.downloadMap = downloadist
        this.notifyDataSetChanged()
    }

    fun update(resourceID : Int, progress : Int, maxProgress : Long) {
        // update progress for a specific resourceID
        // what to do here?
        this.notifyDataSetChanged() // makes app real slow when called repeatedly
    }

    override fun getItemCount(): Int {
        return downloadMap.count()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.save_offline_container_layout, parent, false)
        return SimpleViewHolder(view)
    }

    override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {

        holder.savedData = ArrayList(downloadMap.values)[position]

        if (ArrayList(downloadMap.values)[position].status == "Completed") {
            holder.downloadProgress?.visibility = View.INVISIBLE
        } else {
            holder.downloadProgress?.visibility = View.VISIBLE
//            update progress here??
//            holder.downloadProgress.progress = holder.savedData.progress!!
//            holder.downloadProgress.max = holder.savedData.totalContentLength!!
        }
    }

    inner class SimpleViewHolder(v: View, var savedData: SaveOfflineData? = null) : RecyclerView.ViewHolder(v) {
        var downloadProgress : ProgressBar? = v.findViewById(R.id.saveOffProgress)

    }

}

简化的片段代码:

class SaveOfflineFragment: BaseFragment(), View.OnClickListener{

    var adapter = SaveOfflineAdapter()
    var tabKey = 0

    private var saveOfflineRecyclerView : RecyclerView?       = null

    private val mReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when(intent.action) {
                PROGRESS_UPDATE_ACTION -> {
                    val resId = intent.extras.getInt("resourceID")
                    val progress = intent.extras.getInt("contentLength$resId")
                    val maxProgress = intent.extras.getLong("maxProgress$resId")
                    adapter.update(resId, progress, maxProgress)

                }
                DOWNLOAD_DONE_ACTION -> {
                    loadDataFromBox()
                }

            }

        }
    }


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        rootView = inflater.inflate(R.layout.saveoffline_layout, container, false)
        activity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        ScreenTracking.getInstance().track(TAG_SAVE_OFFLINE_FRAG + tabKey, false)

        getViews()
        setIds()
        setViews()

        return rootView
    }

    private fun getViews() {
        saveOfflineRecyclerView  = rootView!!.recyclerview_main
    }

    private fun setIds(){
        val idRecyclerView: IntArray = intArrayOf(R.id.saveOfflineRecyclerView1, R.id.saveOfflineRecyclerView2, R.id.saveOfflineRecyclerView3, R.id.saveOfflineRecyclerView4)

        val position = tabKey - 1
        saveOfflineRecyclerView!!.id  = idRecyclerView [position]
    }

    private fun setViews(){
        saveOfflineRecyclerView!!.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
        saveOfflineRecyclerView!!.layoutManager!!.isItemPrefetchEnabled = true
        saveOfflineRecyclerView!!.isNestedScrollingEnabled = false
        saveOfflineRecyclerView!!.setHasFixedSize(true)
        saveOfflineRecyclerView!!.setItemViewCacheSize(20)
        saveOfflineRecyclerView!!.isDrawingCacheEnabled = true
        saveOfflineRecyclerView!!.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH
        adapter.hasStableIds()
        saveOfflineRecyclerView!!.adapter = adapter
    }

    override fun onClick(v: View?) {
        when (v!!.id) {
            R.id.saveOfflineSearchBtn1, R.id.saveOfflineSearchBtn2, R.id.saveOfflineSearchBtn3, R.id.saveOfflineSearchBtn4 -> {

            }

            R.id.confirmDeleteCancel -> {

            }

            R.id.confirmDeleteYes -> {

            }

        }
    }

    override fun onResume() {
        println("On resume, registering receiver")
        super.onResume()

        val mIntentFilter = IntentFilter()
        mIntentFilter.addAction(PROGRESS_UPDATE_ACTION)
        mIntentFilter.addAction(DOWNLOAD_DONE_ACTION)
        BuriIOApp.context.registerReceiver(mReceiver, mIntentFilter)
    }

    override fun onPause() {
        println("onpause unregistering receiver")
        BuriIOApp.context.unregisterReceiver(mReceiver)
        super.onPause()
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        tabKey = arguments!!.getInt("tabKey")
        fragmentCallback = context as FragmentCallback
        loadDataFromBox()
    }

    private fun loadDataFromBox(){
        val query = SaveOfflineManager().getAll()
        val saveOfflineData = LinkedHashMap<Int, SaveOfflineData>()
        query.forEach {
            saveOfflineData[it.resourceID!!] = it
        }
        adapter.setData(saveOfflineData)
        adapter.notifyDataSetChanged()


    }

    companion object {
        fun newInstance(tabKey : Int): SaveOfflineFragment {
            val args = Bundle()
            args.putInt("tabKey", tabKey)
            val fragment = SaveOfflineFragment()
            fragment.arguments = args
            return fragment

        }
    }

}

1 个答案:

答案 0 :(得分:1)

update方法中,您必须找到要更新的项目,然后将最后的更改应用于该项目。像这样的东西:

fun update(resourceID : Int, progress : Int, maxProgress : Long) {
    if (downloadMap.get(resourceID)!=null) {
        downloadMap.get(resourceID).progress = progress
        downloadMap.get(resourceID).totalContentLength = maxProgress
    }
    this.notifyDataSetChanged() // makes app real slow when called repeatedly
}

然后在onBindViewHolder方法中,您必须处理进度状态,例如:

Override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {

    holder.savedData = ArrayList(downloadMap.values)[position]

    if (ArrayList(downloadMap.values)[position].status == "Completed") {
        holder.downloadProgress?.visibility = View.INVISIBLE
    } else {
        holder.downloadProgress?.visibility = View.VISIBLE 
        holder.downloadProgress.progress = holder.savedData.progress!!
        holder.downloadProgress.max = holder.savedData.totalContentLength!!
    }
}

提示:在update方法中,您可以使用notifyItemChanged代替notifyDataSetChanged。这是反弹的唯一一项,并且有更好的表现。见下文:

fun update(resourceID : Int, progress : Int, maxProgress : Long) {
    val data = downloadMap.get(resourceID)
    if (data!=null) {
        data.progress = progress
        data.totalContentLength = maxProgress
        val index = ArrayList(downloadMap.values).indexOf(data)
        this.notifyItemChanged(index) 
    }
}