视图不会每次都在回收商列表视图中更新。diff util 对象在第一次不会检测到更改



屏幕录制视频[日志文件是使用相同的确切操作拍摄的]-

屏幕记录

[查看录音了解上下文]我的问题是适配器中的diffutil对象无法检测到第一次进行的更改,因此列表元素不会得到更新。在日志行的右端,您将看到一个真值表。左列应该全部为false。但是,看看第一个值-true。当我启动应用程序时,访问值应该全部为false。当我启动应用程序时,它们都是假的,否则当我启动该应用程序时视频不会以隐藏的所有密码开始。因此,第一次没有将其与实际的旧项目进行比较。但是,改变了旧项目。

适配器diff-util对象的日志输出-

• this is from the initial access. it reads the access. but cannot identify the changes that has been applied. ----making changes the first time -
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   true    true
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:02.695 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   true    true
• look at the first and the last entries. this is the entries they have two trues those are for the olditem and newitem from the diffutil object. lets make another change -
2022-01-11 16:35:26.283 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   true    false
2022-01-11 16:35:26.283 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:26.283 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   false
2022-01-11 16:35:26.283 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:26.284 28084-28153/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   true    false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   true
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_12     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_11     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_10     access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_9      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_8      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_7      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_6      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_5      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_4      access value passed -   false   false
2022-01-11 16:35:26.286 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_3      access value passed -   false   true
2022-01-11 16:35:26.287 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_2      access value passed -   false   false
2022-01-11 16:35:26.287 28084-28146/com.kenetic.savepass I/PassAdapter: id equality checked -   Service_name_1      access value passed -   false   false
here, there are two changes occouring simultaneously. the initial access granted is being revoked and chnaged to false. then, new access is being granted. here since 2 changes are being made, they are being detected.

碎片代码-

package com.kenetic.savepass.fragments
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.navigation.fragment.findNavController
import com.kenetic.savepass.databinding.FragmentSetPasswordBinding
import com.kenetic.savepass.password.data.AppDataStore
class SetPasswordFragment : Fragment() {
private val TAG = "SetPasswordFragmentVKP"
private lateinit var binding: FragmentSetPasswordBinding
private lateinit var appDataStore: AppDataStore
private lateinit var storedPassword: String
private var _symbolsVisibility = MutableLiveData(View.INVISIBLE)
val symbolsVisibility: MutableLiveData<Int> get() = _symbolsVisibility
private var _passwordMatchVisibility = MutableLiveData(View.INVISIBLE)
val passwordMatchVisibility: MutableLiveData<Int> get() = _passwordMatchVisibility
private var _passwordIncorrectVisibility = MutableLiveData(View.INVISIBLE)
val passwordIncorrectVisibility: MutableLiveData<Int> get() = _passwordIncorrectVisibility
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSetPasswordBinding.inflate(inflater, container, false)
binding.setPasswordFragment = this
binding.lifecycleOwner = viewLifecycleOwner
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
appDataStore = AppDataStore(requireContext())
appDataStore.userMasterPasswordFlow.asLiveData().observe(viewLifecycleOwner, {
storedPassword = it
if (it.isEmpty()) {
binding.oldPasswordEditText.visibility = View.GONE
_passwordIncorrectVisibility.value = View.GONE
}
})
binding.saveFab.setOnClickListener { passToNextFrag() }
}
private lateinit var symbolMissingText: String
private fun getSymbolCheckWarning(temp: String): String {
symbolMissingText = ""
val tempTruthList = listOf<Boolean>(
hasUpperCase(temp),
hasLowerCase(temp),
hasSpecial(temp),
hasNumbers(temp),
temp.isNotEmpty()
)
return if (false !in tempTruthList) {
""
} else {
"*missing character types -${symbolMissingText} "
}
}
private fun hasLowerCase(str: String): Boolean {
for (i in str) {
if (i in 'a'..'z') {
return true
}
}
symbolMissingText += " lowercase,"
return false
}
private fun hasUpperCase(str: String): Boolean {
for (i in str) {
if (i in 'A'..'Z') {
return true
}
}
symbolMissingText += " uppercase,"
return false
}
private fun hasSpecial(str: String): Boolean {
for (i in str) {
if (i in "`!@#$%^&*()_-+={[}]|\:;"'<,>.?/") {
return true
}
}
symbolMissingText += " special,"
return false
}
private fun hasNumbers(str: String): Boolean {
for (i in str) {
if (i in '0'..'9') {
return true
}
}
symbolMissingText += " numbers,"
return false
}
private fun getLengthWarningString(str: String): String {
return if (str.length in 9..31) "" else {
"*length should be between 8-32 characters"
}
}
private fun setNewPassWarning(): Boolean {
val str = binding.setNewPasswordEditText.text.toString()
val warningText = getSymbolCheckWarning(str) + getLengthWarningString(str)
Log.i(TAG, "warningText = $warningText")
return if (warningText.isEmpty()) {
_symbolsVisibility.value = View.INVISIBLE
true
} else {
binding.setNewTextView.text = warningText
_symbolsVisibility.value = View.VISIBLE
false
}
}
private fun matchCheck(): Boolean {
return if (binding.setNewPasswordEditText.text.toString() == binding.confirmNewPasswordEditText.text.toString()) {
_passwordMatchVisibility.value = View.INVISIBLE
true
} else {
_passwordMatchVisibility.value = View.VISIBLE
false
}
}
private fun incorrectCheck(): Boolean {
return if (binding.oldPasswordEditText.text.toString() != storedPassword) {
_passwordIncorrectVisibility.value = View.VISIBLE
false
} else {
_passwordIncorrectVisibility.value = View.INVISIBLE
true
}
}
private fun passToNextFrag() {
val tempTruthList = listOf(setNewPassWarning(), matchCheck(), incorrectCheck())
if (false !in tempTruthList) {
appDataStore.editMasterPassword(
binding.setNewPasswordEditText.text.toString(),
requireContext()
)
nextScreen()
} else {
Toast.makeText(requireContext(), "retry again", Toast.LENGTH_SHORT).show()
}
}
private fun nextScreen() {
Log.i(TAG,"next screen called")
this@SetPasswordFragment.findNavController()
.navigate(
SetPasswordFragmentDirections
.actionSetPasswordFragmentToPassListFragment()
)
}
}

适配器代码-

package com.kenetic.savepass.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.kenetic.savepass.R
import com.kenetic.savepass.databinding.PassListBinding
import com.kenetic.savepass.password.PassEnum.Access
import com.kenetic.savepass.password.PasswordData
private const val TAG = "PassAdapter"
class PassAdapter(private val fingerChecker: (PasswordData, Access) -> Unit) :
ListAdapter<PasswordData, PassAdapter.PassViewHolder>(diffCallBack) {

class PassViewHolder(
private val binding: PassListBinding,
private val fingerChecker: (PasswordData, Access) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(passwordData: PasswordData) {
Log.i(TAG, "bind called")
binding.isAppOrWebImageView.setImageResource(
if (passwordData.isAnApplication) {
R.drawable.is_application_icon_24
} else {
R.drawable.is_website_icon_24
}
)
binding.serviceNameTextView.text = passwordData.serviceName
if (passwordData.access) {
Log.i(TAG, "access has been given")
binding.apply {
servicePasswordTextView.text = passwordData.servicePassword
showImageView.setImageResource(R.drawable.ic_baseline_hide_20)
showImageView.setOnClickListener {
fingerChecker(passwordData, Access.HIDE)
}
}
} else {
Log.i(TAG, "access has been denied")
binding.showImageView.setImageResource(R.drawable.ic_baseline_show_20)
binding.servicePasswordTextView.text = "**********"
binding.showImageView.setOnClickListener {
fingerChecker(passwordData, Access.SHOW)
}
}
binding.securityTypeImageView.setImageResource(
if (passwordData.useFingerPrint) {
R.drawable.fingerprint_20
} else {
R.drawable.password_20
}
)
binding.deleteImageView.setOnClickListener {
fingerChecker(passwordData, Access.DELETE)
}
binding.editImageView.setOnClickListener {
Log.d(TAG, "edit image onClick working")
fingerChecker(passwordData, Access.EDIT)
}
}
}
companion object {
private val diffCallBack = object : DiffUtil.ItemCallback<PasswordData>() {
override fun areItemsTheSame(oldItem: PasswordData, newItem: PasswordData): Boolean {
Log.i(
TAG,
"id equality checked -t${oldItem.serviceName}ttaccess value passed - t${oldItem.access}tt${newItem.access}"
)
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: PasswordData, newItem: PasswordData): Boolean {
return (oldItem == newItem && oldItem.access == newItem.access)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PassViewHolder {
return PassViewHolder(
PassListBinding.inflate(LayoutInflater.from(parent.context)), fingerChecker
)
}
override fun onBindViewHolder(holder: PassViewHolder, position: Int) {
Log.i(TAG, "access for $position = ${getItem(position).access}")
holder.bind(getItem(position))
}
}

使用的数据类-

package com.kenetic.savepass.password
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "password_data")
data class PasswordData(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
@ColumnInfo(name = "service_name") var serviceName: String,
@ColumnInfo(name = "service_password") var servicePassword: String,
@ColumnInfo(name = "is_an_application") var isAnApplication: Boolean = false,
@ColumnInfo(name = "use_finger_print") var useFingerPrint: Boolean = true,
@ColumnInfo(name = "access") var access: Boolean = false
)

我尝试将我的元素列表转换为列表,然后将该列表提交给适配器类,将列表的值保存到另一个变量并提交该变量,更改diffutil对象函数以扫描每个元素,然后返回值,等等。

您在哪里将适配器设置为RecyclerView?

试试这个:

binding.recyclerView.adapter?.notifyDataSetChanged()

我们可以做的不是提交一个由多个变量组成的自定义数据类的列表,而是提交一个id(整数(列表,然后在适配器类的onBind部分,使用视图模型函数获取内容,然后使用从该函数接收的内容绑定项。该功能可以看起来像

fun getById(id:Int): Flow<TasksData> = tasksDao.getById(id)

其中getById类似于-

@Query("SELECT * FROM task_data where id = :id")
fun getById(id: Int): Flow<TasksData>

然后,由于它返回一个连续流,我们可以在适配器内的onBind中设置一个观察器,以便每次检测到数据更改时都更新ui。类似

taskViewmodel.getById(getItem(position)).aslivedata.observe{
holder.bind(it)
}

最新更新