首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RecyclerView.Adapter不调用onCreateViewHolder或onBindViewHolder,onAttachedToRecyclerView称为

RecyclerView.Adapter不调用onCreateViewHolder或onBindViewHolder,onAttachedToRecyclerView称为
EN

Stack Overflow用户
提问于 2022-11-03 00:15:07
回答 1查看 66关注 0票数 1

我有获取到适配器使用的游标并调用notifyDataSetChanged()的记录,但是没有调用onCreateViewHolder或onBindViewHolder。正在创建适配器(调用onAttachedToRecyclerView),显然RecyclerView没有显示任何记录。已经看了几个小时了,没有joy。

我已经将代码放在下面,但是这里是logcat,整个项目都是https://github.com/funkytwig/tasktimer

代码语言:javascript
运行
复制
DurationsReportXX    com.funkytwig.takstimer D  onCreate
DurationsReportXX    com.funkytwig.takstimer D  onCreate: Setup adapter
DurationsRVAdapterXX com.funkytwig.takstimer D  onAttachedToRecyclerView
DurationsRVAdapterXX com.funkytwig.takstimer D  onAttachedToRecyclerView done
DurationsReportXX    com.funkytwig.takstimer D  loadData
DurationsReportXX    com.funkytwig.takstimer D  order=Name
AppProviderXX        com.funkytwig.takstimer D  query for uri=content://com.funkytwig.tasktimer.provider/vwTaskDurations
SingletonHolder      com.funkytwig.takstimer D  getInstance
AppProviderXX        com.funkytwig.takstimer D  query: 726 rows returned
DurationsRVAdapterXX com.funkytwig.takstimer D  swapCursor
DurationsRVAdapterXX com.funkytwig.takstimer D  getItemCount: count=0
DurationsRVAdapterXX com.funkytwig.takstimer D  swapCursor newCursor.count=726, oldCursor.cont=null
DurationsRVAdapterXX com.funkytwig.takstimer D  swapCursor notify the observers about the new cursor
RecyclerView         com.funkytwig.takstimer E  No adapter attached; skipping layout
EGL_emulation        com.funkytwig.takstimer D  eglMakeCurrent: 0xe837ed40: ver 2 0 (tinfo 0xe83c0760)
EGL_emulation        com.funkytwig.takstimer D  eglMakeCurrent: 0xe837ed40: ver 2 0 (tinfo 0xe83c0760)
EGL_emulation        com.funkytwig.takstimer D  eglMakeCurrent: 0xe837ed40: ver 2 0 (tinfo 0xe83c0760)
chatty               com.funkytwig.takstimer I  uid=10162(com.funkytwig.takstimer) RenderThread identical 1 line
EGL_emulation        com.funkytwig.takstimer D  eglMakeCurrent: 0xe837ed40: ver 2 0 (tinfo 0xe83c0760)
MainActivityXX       com.funkytwig.takstimer D  onStop
EGL_emulation        com.funkytwig.takstimer D  eglMakeCurrent: 0xe837ed40: ver 2 0 (tinfo 0xe83c0760)

想知道“没有适配器附加;跳过布局”是相关的,奇怪的是,因为avapter肯定是附加的。想知道我是否可以在RecyclerView中打开一些调试?

DurationsRVAdapter

代码语言:javascript
运行
复制
package com.funkytwig.tasktimer

import android.content.Context
import android.database.Cursor
import android.text.format.DateFormat
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.funkytwig.tasktimer.databinding.TaskDurationItemsBinding
import java.util.Locale
import java.lang.IllegalStateException

private const val TAG = "DurationsRVAdapterXX"

class DurationsRVAdapter(context: Context, private var cursor: Cursor?) :
    RecyclerView.Adapter<DurationsRVAdapter.DurationsViewHolder>() {

     inner class DurationsViewHolder(val bindings: TaskDurationItemsBinding) :
        RecyclerView.ViewHolder(bindings.root)

    private val dateFormat = DateFormat.getDateFormat(context)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DurationsViewHolder {
        Log.d(TAG, "onCreateViewHolder")
        val view =
            TaskDurationItemsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return DurationsViewHolder(view)

    }

    override fun onBindViewHolder(holder: DurationsViewHolder, position: Int) {
        val func = "onBindViewHolder"
        Log.d(TAG, "$func: position = $position")
        val cursor = cursor

        if (cursor != null && cursor.count != 0) {
            if (!cursor.moveToPosition(position)) {
                throw IllegalStateException("Couldn't move cursor to position $position")
            }
            val name = cursor.getString(cursor.getColumnIndex(DurationsContract.Columns.NAME))
            val description =
                cursor.getString(cursor.getColumnIndex(DurationsContract.Columns.DESCRIPTION))
            val startTime =
                cursor.getLong(cursor.getColumnIndex(DurationsContract.Columns.START_TIME))
            val totalDuration =
                cursor.getLong(cursor.getColumnIndex(DurationsContract.Columns.DURATION))
            val userDate =
                dateFormat.format(startTime * 1000)  // The database stores seconds, we need milliseconds
            val totalTime = formatDuration(totalDuration)

            holder.bindings.tdName.text = name
            holder.bindings.tdDescription?.text = description
            holder.bindings.tdStart.text = userDate
            holder.bindings.tdDuration.text = totalTime
        }
    }

    private fun formatDuration(duration: Long): String {
        // convert duration Long to hours:mins:secs String (can be > 24 hours so cant use dateFormat)
        val hours = duration / 3600
        val remainder = duration - hours * 3600
        val minutes = remainder / 60
        val seconds = remainder % 60
        return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds)
    }

    override fun getItemCount(): Int {
        val func = "getItemCount"
        val count = cursor?.count ?: 0
        Log.d(TAG, "$func: count=$count")
        return count
    }

    fun swapCursor(newCursor: Cursor?): Cursor? {
        val func = "swapCursor"
        Log.d(TAG, func)
        if (newCursor === cursor) return null

        val numItems = itemCount
        val oldCursor = cursor
        cursor = newCursor

        Log.d(TAG, "$func newCursor.count=${newCursor?.count}, oldCursor.cont=${oldCursor?.count}")

        if (newCursor != null) {
            Log.d(TAG, "$func notify the observers about the new cursor")
            // notify the observers about the new cursor
            notifyDataSetChanged()
        } else {
            Log.d(TAG, "$func Notify observer about lack of dataset")
            // Notify observer about lack of dataset, all of it from 0 to newItems,
            // i.e. whole range of records has gone
            notifyItemRangeChanged(0, numItems)
        }
        return oldCursor
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        val func = "onAttachedToRecyclerView"
        Log.d(TAG, func)
        super.onAttachedToRecyclerView(recyclerView)
        Log.d(TAG, "$func done")
    }
}

这是一个用于显示报表记录的RecyclerView。我正在用一个活动来测试它(当我让它工作时,它会把大部分代码放到ViewModel中)。

DurationsReport.kt

代码语言:javascript
运行
复制
package com.funkytwig.tasktimer

import android.database.Cursor
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.funkytwig.tasktimer.databinding.ActivityDurationsReportBinding
import com.funkytwig.tasktimer.databinding.TaskDurationsBinding

private const val TAG = "DurationsReportXX"

enum class SortColumns { NAME, DESCRIPTION, START_DATE, DURATION }

class DurationsReport : AppCompatActivity() {
    private val reportAdapter by lazy { DurationsRVAdapter(this, null) }
    var databaseCursor: Cursor? = null
    var sortOrder = SortColumns.NAME
    private val selection = "${DurationsContract.Columns.START_TIME} BETWEEN ? AND ?"
    private var selectionArgs = arrayOf("0" , "1559347199")

    private lateinit var binding: ActivityDurationsReportBinding
    private lateinit var tdBinding: TaskDurationsBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        val func = "onCreate"
        Log.d(TAG, func)
        super.onCreate(savedInstanceState)

        binding = ActivityDurationsReportBinding.inflate(layoutInflater)
        tdBinding = TaskDurationsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setSupportActionBar(binding.toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        Log.d(TAG, "$func: Setup adapter")

        tdBinding.tdList.layoutManager = LinearLayoutManager(this)
        tdBinding.tdList.adapter = reportAdapter

        loadData()
    }

    private fun loadData() {
        val func = "loadData"
        Log.d(TAG, func)
        val order = when (sortOrder) {
            SortColumns.NAME -> DurationsContract.Columns.NAME
            SortColumns.DESCRIPTION -> DurationsContract.Columns.DESCRIPTION
            SortColumns.START_DATE -> DurationsContract.Columns.START_DATE
            SortColumns.DURATION -> DurationsContract.Columns.DURATION
        }
        Log.d(TAG, "order=$order")
      //  GlobalScope.launch {
            val cursor = application.contentResolver.query(
                DurationsContract.CONTENT_URI, null, selection, selectionArgs, order
            )
            databaseCursor = cursor
            reportAdapter.swapCursor(cursor)?.close()
     //   }
    }
}

该活动的主要布局是activity_durations_report.xml

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DurationsReport">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.TasksTimer.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.TasksTimer.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/task_durations" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

其中包含task_durations.xml (这里有报告的标题)

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_constraintHorizontal_chainStyle="spread">

    <TextView
        android:id="@+id/td_name_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_name"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread" />

    <TextView
        android:id="@+id/td_start_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginEnd="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_date"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintBaseline_toBaselineOf="@+id/td_name_heading"
        app:layout_constraintEnd_toStartOf="@+id/td_duration_heading"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/td_name_heading" />

    <TextView
        android:id="@+id/td_duration_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginEnd="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_duration"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintBaseline_toBaselineOf="@+id/td_start_heading"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/td_start_heading" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/td_list"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/td_name_heading"
        app:layout_constraintVertical_bias="0.142"
        tools:listitem="@layout/task_duration_items" />
</androidx.constraintlayout.widget.ConstraintLayout>

RecyclerView适配器使用task_durations_items.xml

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_constraintHorizontal_chainStyle="spread">

    <TextView
        android:id="@+id/td_name_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_name"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread" />

    <TextView
        android:id="@+id/td_start_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginEnd="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_date"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintBaseline_toBaselineOf="@+id/td_name_heading"
        app:layout_constraintEnd_toStartOf="@+id/td_duration_heading"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/td_name_heading" />

    <TextView
        android:id="@+id/td_duration_heading"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginEnd="4dp"
        android:background="?attr/colorButtonNormal"
        android:padding="4dp"
        android:text="@string/td_text_duration"
        android:textAlignment="viewStart"
        android:textStyle="bold"
        app:layout_constraintBaseline_toBaselineOf="@+id/td_start_heading"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/td_start_heading" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/td_list"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/td_name_heading"
        app:layout_constraintVertical_bias="0.142"
        tools:listitem="@layout/task_duration_items" />
</androidx.constraintlayout.widget.ConstraintLayout>
EN

回答 1

Stack Overflow用户

发布于 2022-11-03 05:50:45

您提到“想知道”是否“没有附加适配器;跳过布局”是相关的“。你没有附上布局管理器吗?

请在回收器视图中尝试Xml布局中的以下代码

代码语言:javascript
运行
复制
<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvVisas"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="40dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:listitem="@layout/item_visa" />

如果您没有附加任何布局经理回收视图将不会显示任何数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74296913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档