简体   繁体   English

如何在回收站视图中回收视图

[英]how to recycle view in Recycler View

I am using Recycler view to create List View. 我正在使用Recycler视图创建列表视图。 With in the List View, Each of the item has Horizontal Scroll bar. 在列表视图中,每个项目都有水平滚动条。 In the horizontal scroll bar, I display either one item or 3 items based on particular business logic. 在水平滚动条中,我根据特定的业务逻辑显示一项或三项。 When listed, the first 2 scrolls display exactly what I wanted. 列出后,前2个滚动条完全显示我想要的内容。 But for further scrolls, I am having problem with the items that I display in the Horizontal Scroll view. 但是对于进一步的滚动,我在“水平滚动”视图中显示的项目有问题。 It displays multiple items where only one item should be there. 它显示多个项目,其中仅应有一个项目。 When investigated, I came to know that its because, the view is not recycled. 经过调查,我知道这是因为,视图未被回收。

After searching, I override this function, onViewRecycled. 搜索后,我重写了onViewRecycled这个函数。 This function is called when the issue starts (third and further on scrolls). 当问题开始时(滚动第三和更远),将调用此函数。 I don't know how to fix this issue. 我不知道如何解决此问题。 I am passing List of History to adapter at the beginning itself. 我一开始就将历史列表传递给适配器。

Kindly help me to resolve this. 请帮助我解决这个问题。

public class HistoryAdapter(users:List<HistoryItem>): RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {

    val TAG = "HistoryAdapter"

    var historyList:List<HistoryItem>? =null
    var context: Context? =null

    init {
        historyList = users

    }

    override fun onViewRecycled(holder: ViewHolder?) {
        super.onViewRecycled(holder)
        Log.d(TAG,"********************************************************************************************************************************Views are recycled****************************")

        if (holder is HistoryAdapter.ViewHolder) {

            val handler = Handler()
            handler.post(Runnable { () -> notifyItemRemoved(holder.getOldPosition()) })
            //notifyItemRangeChanged(holder.getAdapterPosition(),historyList!!.size())
        }

    }

    override fun getItemId(position: Int): Long {
        return super.getItemId(position)
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        var lung: Boolean? = false
        var tag: String? = null
        val historyItem: HistoryItem = historyList!!.get(position)

        holder!!.profileImg.setImageBitmap(BitmapFactory.decodeFile(File(Environment.getDataDirectory().getAbsolutePath(), "data/" + context!!.getPackageName() + "/files/users/" + historyItem.uuidVal + "/portrait.png").getAbsolutePath()))

        holder!!.notesTxt.setText(historyItem.sessionVal!!.getNote())

        val date = historyItem.sessionVal!!.getDate()
        var formatDayOfMonth  = SimpleDateFormat("dd");
        val day = Integer.parseInt(formatDayOfMonth.format(date));
        val dayStr = day.toString();

        formatDayOfMonth  = SimpleDateFormat("MMM")
        val month = formatDayOfMonth.format(date)

        formatDayOfMonth = SimpleDateFormat("yyyy")
        val year = formatDayOfMonth.format(date)

        formatDayOfMonth = SimpleDateFormat("hh:mm a")
        val currentTime = formatDayOfMonth.format(date)


        val dateStr = month+" "+dayStr+", "+year

        holder!!.dateTxt.setText(dateStr)
        holder!!.timeTxt.setText(currentTime)

        Log.d(TAG,"********************************************************************************************************************************************user =>"+historyItem.uuidVal);
        Log.d(TAG,"********************************************************************************************************************************************current time =>"+currentTime);

        var ambientTemp: Double? = null
        var surfaceTemp: Double? = null
        var coreBodyTemp: Double? = null

        var heartRate: Int? = null
        var lungAvailable: Boolean = false
        var heartAvailable: Boolean = false
        var tempAvailable: Boolean = false

        try {
            val tempRecording:TemperatureRecording = checkNotNull(historyItem.sessionVal!!.getTemperature())
            tempAvailable = true
            ambientTemp = tempRecording.getAmbientTemp()
            surfaceTemp = tempRecording.getSurfaceTemp()
            coreBodyTemp = TemperatureRecording.CalculateCoreBodyTemperature.getCoreBodyTemp(ambientTemp,surfaceTemp)
        } catch(i: IllegalStateException) {
            Log.w(TAG,"Temperature not available for user session")
            tempAvailable = false
        }

        try {
            val heartRecording:HeartRecording = checkNotNull(historyItem.sessionVal!!.getHeart())
            heartAvailable = true
            heartRate = heartRecording.getHeartRate()
        } catch(i: IllegalStateException) {
            Log.w(TAG,"Heart not available for user session")
            heartAvailable = false
        }

        try {
            val lungRecording:LungsRecording = checkNotNull(historyItem.sessionVal!!.getLungs())
            lungAvailable = true
        } catch(i: IllegalStateException) {
            Log.w(TAG,"Lung not available for user session")
            lungAvailable = false
        }



        Log.d(TAG,"********************************************************************************************************************************************temperature =>"+tempAvailable)
        Log.d(TAG,"********************************************************************************************************************************************heart =>"+heartAvailable)
        Log.d(TAG,"********************************************************************************************************************************************lung =>"+lungAvailable)

        //Log.d(TAG,"********************************************************************************************************************************************ambient temp val =>"+ambientTemp)
        //Log.d(TAG,"********************************************************************************************************************************************surface temp val =>"+surfaceTemp)
        //Log.d(TAG,"********************************************************************************************************************************************heart val =>"+heartRate)
        //Log.d(TAG,"********************************************************************************************************************************************lung val =>"+historyItem.sessionVal!!.getLungs())

        val parentLinearLayout = holder!!.readingsView
        //createLayout(holder!!.readingsView,tag,coreBodyTemp,heartRate)
        var childLinearLayout: LinearLayout? = null

        if(tempAvailable == true && heartAvailable == true && lungAvailable == true) {
            for(i in 1..3) {
                if(i == 1) {
                    val df = DecimalFormat("#.##");
                    childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.temperature), df.format(coreBodyTemp).toString(), context!!.getString(R.string.temperatureStr))
                    parentLinearLayout.addView(childLinearLayout)
                    childLinearLayout = null
                } else if(i == 2) {
                    childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.heart), heartRate.toString(), context!!.getString(R.string.heartRate))
                    parentLinearLayout.addView(childLinearLayout)
                    childLinearLayout = null
                } else if(i == 3) {
                    childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.lung), "", "")
                    parentLinearLayout.addView(childLinearLayout)
                    childLinearLayout = null
                }
            }
        } else if (tempAvailable) {
            val df = DecimalFormat("#.##");
            childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.temperature), df.format(coreBodyTemp).toString(), context!!.getString(R.string.temperatureStr))
            parentLinearLayout.addView(childLinearLayout)
            childLinearLayout = null
        } else if (heartAvailable) {
            childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.heart), heartRate.toString(), context!!.getString(R.string.heartRate))
            parentLinearLayout.addView(childLinearLayout)
            childLinearLayout = null
        } else if (lungAvailable) {
            childLinearLayout = createChildView(BitmapFactory.decodeResource(context!!.getResources(),R.drawable.lung), "", "")
            parentLinearLayout.addView(childLinearLayout)
            childLinearLayout = null
        }



    }

    fun createChildView(icon: Bitmap,readingVal: String, readingTag: String) : LinearLayout {
        val lp = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT)
        lp.weight = 1f
        val parent: LinearLayout = LinearLayout(context!!)
        parent.setOrientation(LinearLayout.HORIZONTAL)
        parent.setLayoutParams(lp)

        val imageView = ImageView(context!!)
        val layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT)
        layoutParams.weight = 0.4f
        layoutParams.leftMargin = 10
        layoutParams.rightMargin = 10
        layoutParams.topMargin = 10
        layoutParams.bottomMargin =10

        imageView.setLayoutParams(layoutParams)
        imageView.setImageBitmap(icon)
        parent.addView(imageView)


        val readingLayout = LinearLayout(context!!)
        readingLayout.setOrientation(LinearLayout.VERTICAL)
        val lp1 = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT)
        lp1.weight = 0.6f
        lp1.topMargin = 10
        readingLayout.setLayoutParams(lp)

        val displayValue = TextView(context!!)
        val layoutParams1 = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 0)
        layoutParams1.weight = 0.7f
        displayValue.setLayoutParams(layoutParams1)
        displayValue.setText(readingVal)
        readingLayout.addView(displayValue)

        val displayTag = TextView(context!!)
        layoutParams1.weight = 0.3f
        displayTag.setLayoutParams(layoutParams1)
        displayTag.setText(readingTag)
        readingLayout.addView(displayTag)


        parent.addView(readingLayout)

        return parent


    }

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder? {
        context = parent!!.getContext()
        // create a new view
        val v: View = LayoutInflater.from(parent!!.getContext())
                .inflate(R.layout.layout_history_row, parent, false);

        return ViewHolder(v)
    }

    override fun getItemCount(): Int {
        return historyList!!.size()

    }

    public class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        public var profileImg: ImageView
        public var dateTxt: TextView
        public var timeTxt: TextView
        public var locationTxt: TextView
        public var notesTxt: TextView
        //public var icon: ImageView
        //public var readingTxt: TextView
        //public var readingDescTxt: TextView

        public var readingsView: LinearLayout


        init {
            profileImg = itemView.findViewById(R.id.profileImage) as ImageView
            dateTxt = itemView.findViewById(R.id.date) as TextView
            timeTxt = itemView.findViewById(R.id.time) as TextView
            locationTxt = itemView.findViewById(R.id.location) as TextView
            notesTxt = itemView.findViewById(R.id.notes) as TextView
            //readingTxt = itemView.findViewById(R.id.readings) as TextView
            //readingDescTxt = itemView.findViewById(R.id.readingsDesc) as TextView
//            icon = itemView.findViewById(R.id.icon) as ImageView
            readingsView = itemView.findViewById(R.id.readingsView) as LinearLayout
        }
    }
}

Activity code 活动代码

val history = findViewById(R.id.history) as RecyclerView
for(user in allUsers) {
            val uuid: String? = user.getId()
            Log.d(TAG,"*****************************************************************************************************************UUID=>"+uuid+"FirstName=>"+user.getFirstName()+",sessions size =>"+user.getSessions().size())
            for(session in user.getSessions()) {
                historyItems.add(HistoryItem(user.getId(),session))
            }
        }

history.setHasFixedSize(true);
        history.setAdapter(HistoryAdapter(historyItems))
        history.setLayoutManager(LinearLayoutManager(this))

I don't know what kind of "recycling" you're expecting, but what the RecyclerView does is that it will call onCreateViewHolder() until it has enough viewholders to cover slightly more than what is visible on the screen. 我不知道您期望什么样的“回收”,但是RecyclerView的作用是它将调用onCreateViewHolder()直到它具有足够的视口以覆盖屏幕上可见的内容为止。 It will then call onBindViewHolder() to populate the data in the created viewholders. 然后,它将调用onBindViewHolder()来填充创建的视图持有人中的数据。

When you start scrolling, it will grab one of the already created viewholders and feed it back into onBindViewHolder() with a new position . 当您开始滚动时,它将抓取一个已经创建的viewholder,并将其以新position反馈到onBindViewHolder() It doesn't do any magic resetting of the viewholder. 它不会对视点保持器进行任何神奇的重置。

In your case, you're never resetting the readingsView , so the adapter keeps adding children to it (which is why it contains more children than expected as you scroll further through the data). 在您的情况下,您永远不会重置readingsView ,因此适配器会继续向其添加子项(这就是为什么当您进一步滚动数据时它包含比预期更多的子项的原因)。 In onBindViewHolder() you'll need to remove all existing children from readingsView before you start adding new ones. onBindViewHolder() ,在开始添加新的子级之前,您需要从readingsView删除所有现有的子级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM