RecyclerView 适配器不通知 DataSetChanged
RecycledView adapter doesnt notify DataSetChanged
我有 MainActivity 和 NavigationDrawer,当我按下 "AddNewDevice" 我想用空 RecycledView 实现名为 "AddNewDeviceFragment" 的片段。然后当我按下 "refreshButton" 时,我的 RecycledView 应该通过 LiveData.[=15 更新=]
当我按下按钮时没有发生任何事情,而不是这个。看起来实时数据观察器不起作用,因为如果我通过 NewDeviceAdapter 方法添加数据,调用 addDevice 回收视图通知更改。
我的代码如下:
MainActivity
lateinit var auth: FirebaseAuth
lateinit var toolbar: Toolbar
lateinit var drawerLayout: DrawerLayout
lateinit var navView: NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
drawerLayout = findViewById(R.id.drawer_layout)
navView = findViewById(R.id.nav_view)
val toggle: ActionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, 0, 0)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
supportFragmentManager.beginTransaction().replace(R.id.content_layout,
AllDevicesFragment()
).commit()
navView.setCheckedItem(R.id.nav_allDevices)
Validator.validateInternetConnection(baseContext)
}
override fun onBackPressed() {
if(supportFragmentManager.backStackEntryCount == 0){
supportFragmentManager.popBackStack()
} else {
super.onBackPressed()
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
updateHeader()
var fragment : Fragment = Fragment()
item.setChecked(true)
when (item.itemId) {
R.id.nav_profile -> {
fragment = ProfileFragment()
}
R.id.nav_allDevices -> {
fragment = AllDevicesFragment()
}
R.id.nav_addNewDevice -> {
fragment = AddNewDeviceFragment()
}
R.id.nav_contact -> {
fragment = ContactFragment()
}
R.id.nav_updateUser -> {
fragment = UpdateUserFragment()
}
R.id.nav_logout -> {
auth.signOut()
finish()
startActivity(Intent(this, LoginActivity::class.java))
}
}
supportFragmentManager
.beginTransaction()
.replace(R.id.content_layout,fragment)
.addToBackStack("fragments")
.commit()
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
fun updateHeader(){
//TODO Zrobić tak żeby aktualizowało header jak się otwiera navigation drawer
var username : TextView = navView.getHeaderView(0).findViewById(R.id.navUsername)
var email : TextView = navView.getHeaderView(0).findViewById(R.id.navEmmailAddres)
var profilePicture : ImageView = navView.getHeaderView(0).findViewById(R.id.navProfilePicture)
username.setText(auth.currentUser?.displayName)
email.setText(auth.currentUser?.email)
Glide.with(this)
.load(auth.currentUser?.photoUrl)
.into(profilePicture)
}
AddNewDeviceFragment
class AddNewDeviceFragment : Fragment() {
private var newDevices: MutableList<NewDevice> = arrayListOf()
private var adapter: NewDeviceAdapter = NewDeviceAdapter(arrayListOf())
private lateinit var model: NewDeviceViewModel
private lateinit var rootView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_addnewdevice, container, false)
return rootView
}
override fun onStart() {
super.onStart()
var newDevicesRecycledView = rootView.findViewById(R.id.newDevicesRecycledView) as RecyclerView
newDevicesRecycledView.layoutManager = LinearLayoutManager(activity)
newDevicesRecycledView.adapter = adapter
//ViewModel
model = ViewModelProviders.of(this).get(NewDeviceViewModel::class.java)
//LiveData
model.getNewDevices().observe(viewLifecycleOwner, Observer<MutableList<NewDevice>> { newDevices ->
adapter.addDevice(newDevices)
})
refreshButton.setOnClickListener{addToRecycledView()}
}
fun addToRecycledView(){
model.addNewDevice(NewDevice("10.121.125.57"))
}
}
新设备适配器
package com.example.lightmeup.NewDevice
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.lightmeup.Entity.NewDevice
import com.example.lightmeup.R
class NewDeviceAdapter(var newDevices: MutableList<NewDevice>): RecyclerView.Adapter<NewDeviceViewHolder>() {
//number of items
override fun getItemCount(): Int {
return newDevices.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewDeviceViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.device_in_acces_point_state_item, parent ,false)
return NewDeviceViewHolder(cellForRow)
}
override fun onBindViewHolder(holder: NewDeviceViewHolder, position: Int) {
holder.bind(newDevices[position])
}
fun addDevice( data: MutableList<NewDevice>){
this.newDevices = data
notifyDataSetChanged()
}
}
NewDeviceViewHolder
package com.example.lightmeup.NewDevice
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.example.lightmeup.Entity.NewDevice
import kotlinx.android.synthetic.main.device_in_acces_point_state_item.view.*
class NewDeviceViewHolder(val view: View): RecyclerView.ViewHolder(view){
fun bind(newDevice: NewDevice) = with(view){
device_name.text = newDevice.name
}
}
NewDeviceViewModel
package com.example.lightmeup.NewDevice
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import com.example.lightmeup.Entity.NewDevice
class NewDeviceViewModel(application: Application) : AndroidViewModel(application) {
val allNewDevices: MutableLiveData<MutableList<NewDevice>> by lazy {MutableLiveData<MutableList<NewDevice>>()}
val newDevices: MutableList<NewDevice> = arrayListOf()
init {
addNewDevice(NewDevice("JAJko"))
}
fun getNewDevices(): MutableLiveData<MutableList<NewDevice>>{
return allNewDevices
}
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
}
}
您的实时数据从未更新,因为您的视图模型仅将新数据添加到列表而不是实时数据。所以你的代码中应该有这一行。
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
allNewDevices.value = newDevices
}
您正在 addNewDevice 函数内更新 newDevices,但您没有在任何地方更新 LiveData。您必须更新 allNewDevices,例如在 addNewDevice 函数内部,如下所示:
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
allNewDevices.value = newDevices
}
我有 MainActivity 和 NavigationDrawer,当我按下 "AddNewDevice" 我想用空 RecycledView 实现名为 "AddNewDeviceFragment" 的片段。然后当我按下 "refreshButton" 时,我的 RecycledView 应该通过 LiveData.[=15 更新=]
当我按下按钮时没有发生任何事情,而不是这个。看起来实时数据观察器不起作用,因为如果我通过 NewDeviceAdapter 方法添加数据,调用 addDevice 回收视图通知更改。
我的代码如下:
MainActivity
lateinit var auth: FirebaseAuth
lateinit var toolbar: Toolbar
lateinit var drawerLayout: DrawerLayout
lateinit var navView: NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
drawerLayout = findViewById(R.id.drawer_layout)
navView = findViewById(R.id.nav_view)
val toggle: ActionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, 0, 0)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
supportFragmentManager.beginTransaction().replace(R.id.content_layout,
AllDevicesFragment()
).commit()
navView.setCheckedItem(R.id.nav_allDevices)
Validator.validateInternetConnection(baseContext)
}
override fun onBackPressed() {
if(supportFragmentManager.backStackEntryCount == 0){
supportFragmentManager.popBackStack()
} else {
super.onBackPressed()
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
updateHeader()
var fragment : Fragment = Fragment()
item.setChecked(true)
when (item.itemId) {
R.id.nav_profile -> {
fragment = ProfileFragment()
}
R.id.nav_allDevices -> {
fragment = AllDevicesFragment()
}
R.id.nav_addNewDevice -> {
fragment = AddNewDeviceFragment()
}
R.id.nav_contact -> {
fragment = ContactFragment()
}
R.id.nav_updateUser -> {
fragment = UpdateUserFragment()
}
R.id.nav_logout -> {
auth.signOut()
finish()
startActivity(Intent(this, LoginActivity::class.java))
}
}
supportFragmentManager
.beginTransaction()
.replace(R.id.content_layout,fragment)
.addToBackStack("fragments")
.commit()
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
fun updateHeader(){
//TODO Zrobić tak żeby aktualizowało header jak się otwiera navigation drawer
var username : TextView = navView.getHeaderView(0).findViewById(R.id.navUsername)
var email : TextView = navView.getHeaderView(0).findViewById(R.id.navEmmailAddres)
var profilePicture : ImageView = navView.getHeaderView(0).findViewById(R.id.navProfilePicture)
username.setText(auth.currentUser?.displayName)
email.setText(auth.currentUser?.email)
Glide.with(this)
.load(auth.currentUser?.photoUrl)
.into(profilePicture)
}
AddNewDeviceFragment
class AddNewDeviceFragment : Fragment() {
private var newDevices: MutableList<NewDevice> = arrayListOf()
private var adapter: NewDeviceAdapter = NewDeviceAdapter(arrayListOf())
private lateinit var model: NewDeviceViewModel
private lateinit var rootView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_addnewdevice, container, false)
return rootView
}
override fun onStart() {
super.onStart()
var newDevicesRecycledView = rootView.findViewById(R.id.newDevicesRecycledView) as RecyclerView
newDevicesRecycledView.layoutManager = LinearLayoutManager(activity)
newDevicesRecycledView.adapter = adapter
//ViewModel
model = ViewModelProviders.of(this).get(NewDeviceViewModel::class.java)
//LiveData
model.getNewDevices().observe(viewLifecycleOwner, Observer<MutableList<NewDevice>> { newDevices ->
adapter.addDevice(newDevices)
})
refreshButton.setOnClickListener{addToRecycledView()}
}
fun addToRecycledView(){
model.addNewDevice(NewDevice("10.121.125.57"))
}
}
新设备适配器
package com.example.lightmeup.NewDevice
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.lightmeup.Entity.NewDevice
import com.example.lightmeup.R
class NewDeviceAdapter(var newDevices: MutableList<NewDevice>): RecyclerView.Adapter<NewDeviceViewHolder>() {
//number of items
override fun getItemCount(): Int {
return newDevices.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewDeviceViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.device_in_acces_point_state_item, parent ,false)
return NewDeviceViewHolder(cellForRow)
}
override fun onBindViewHolder(holder: NewDeviceViewHolder, position: Int) {
holder.bind(newDevices[position])
}
fun addDevice( data: MutableList<NewDevice>){
this.newDevices = data
notifyDataSetChanged()
}
}
NewDeviceViewHolder
package com.example.lightmeup.NewDevice
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.example.lightmeup.Entity.NewDevice
import kotlinx.android.synthetic.main.device_in_acces_point_state_item.view.*
class NewDeviceViewHolder(val view: View): RecyclerView.ViewHolder(view){
fun bind(newDevice: NewDevice) = with(view){
device_name.text = newDevice.name
}
}
NewDeviceViewModel
package com.example.lightmeup.NewDevice
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import com.example.lightmeup.Entity.NewDevice
class NewDeviceViewModel(application: Application) : AndroidViewModel(application) {
val allNewDevices: MutableLiveData<MutableList<NewDevice>> by lazy {MutableLiveData<MutableList<NewDevice>>()}
val newDevices: MutableList<NewDevice> = arrayListOf()
init {
addNewDevice(NewDevice("JAJko"))
}
fun getNewDevices(): MutableLiveData<MutableList<NewDevice>>{
return allNewDevices
}
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
}
}
您的实时数据从未更新,因为您的视图模型仅将新数据添加到列表而不是实时数据。所以你的代码中应该有这一行。
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
allNewDevices.value = newDevices
}
您正在 addNewDevice 函数内更新 newDevices,但您没有在任何地方更新 LiveData。您必须更新 allNewDevices,例如在 addNewDevice 函数内部,如下所示:
fun addNewDevice(newDevice: NewDevice) {
newDevices.add(newDevice)
allNewDevices.value = newDevices
}