视图不会每次都在回收站列表视图中更新。 diff util 对象不会在第一次检测到更改
views aren't getting updated in recycler list view every time. diff util object won't detect change the first time
一个屏幕录制视频[日志文件是使用完全相同的操作获取的] -
[观看录音了解上下文] 我的问题是适配器中的 diffutil 对象无法检测到第一次所做的更改,因此列表元素不会更新。在日志行的右端,您会看到一个真值 table。左栏应该都是假的。但是,请看第一个值 - true。当我启动应用程序时,访问值应该全部为假。当我启动该应用程序时,它们都是错误的,否则当我启动该应用程序时,视频不会以隐藏的所有密码开始。因此,第一次没有对实际的旧项目进行比较。但是,更改后的旧项目。
适配器差异实用程序对象的日志输出 -
• 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}\t\taccess value passed - \t${oldItem.access}\t\t${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))
}
}
使用的数据class -
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
)
我已经尝试将我的元素列表转换为列表,然后将该列表提交给适配器 class,将列表的值保存到另一个变量并提交该变量,更改 diffutil 对象函数以扫描每个元素然后 return 值等
你在哪里设置 RecyclerView 的适配器?
试试这个:
binding.recyclerView.adapter?.notifyDataSetChanged()
我们可以提交一个 id(整数)列表,然后在适配器的 onBind 部分提交一个包含多个变量的自定义数据列表 class,而不是提交一个列表class,使用视图模型函数获取内容,然后使用从该函数接收的内容绑定项目。该函数看起来像 -
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)
}
一个屏幕录制视频[日志文件是使用完全相同的操作获取的] -
[观看录音了解上下文] 我的问题是适配器中的 diffutil 对象无法检测到第一次所做的更改,因此列表元素不会更新。在日志行的右端,您会看到一个真值 table。左栏应该都是假的。但是,请看第一个值 - true。当我启动应用程序时,访问值应该全部为假。当我启动该应用程序时,它们都是错误的,否则当我启动该应用程序时,视频不会以隐藏的所有密码开始。因此,第一次没有对实际的旧项目进行比较。但是,更改后的旧项目。
适配器差异实用程序对象的日志输出 -
• 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}\t\taccess value passed - \t${oldItem.access}\t\t${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))
}
}
使用的数据class -
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
)
我已经尝试将我的元素列表转换为列表,然后将该列表提交给适配器 class,将列表的值保存到另一个变量并提交该变量,更改 diffutil 对象函数以扫描每个元素然后 return 值等
你在哪里设置 RecyclerView 的适配器?
试试这个:
binding.recyclerView.adapter?.notifyDataSetChanged()
我们可以提交一个 id(整数)列表,然后在适配器的 onBind 部分提交一个包含多个变量的自定义数据列表 class,而不是提交一个列表class,使用视图模型函数获取内容,然后使用从该函数接收的内容绑定项目。该函数看起来像 -
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)
}