从广播接收器更新 Recyclerview 中的进度条
Update Progressbar in Recyclerview from Broadcast Receiver
我正在尝试弄清楚如何在收到接收方的进度更新后更新特定项目的进度条。
这是我在片段中的接收器:
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
}
}
}
在 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)
}
}
我正在尝试弄清楚如何在收到接收方的进度更新后更新特定项目的进度条。
这是我在片段中的接收器:
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
}
}
}
在 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)
}
}