我有获取到适配器使用的游标并调用notifyDataSetChanged()的记录,但是没有调用onCreateViewHolder或onBindViewHolder。正在创建适配器(调用onAttachedToRecyclerView),显然RecyclerView没有显示任何记录。已经看了几个小时了,没有joy。
我已经将代码放在下面,但是这里是logcat,整个项目都是https://github.com/funkytwig/tasktimer。
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
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
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。
<?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 (这里有报告的标题)
<?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
<?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>
发布于 2022-11-03 05:50:45
您提到“想知道”是否“没有附加适配器;跳过布局”是相关的“。你没有附上布局管理器吗?
请在回收器视图中尝试Xml布局中的以下代码
<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" />
如果您没有附加任何布局经理回收视图将不会显示任何数据。
https://stackoverflow.com/questions/74296913
复制相似问题