【发布时间】:2020-02-02 10:23:15
【问题描述】:
尝试使用 Retrofit 从服务器获取数据并使用 Room Database 离线缓存。
问题 我已从服务器获取数据并将其插入房间,但无法填充。计算表达式后,LiveData 列表为空。
我确信插入是成功的,因为我在 StackOverflow 上查看了一些答案,其中提到返回 ID 列表以查明是否有插入。
下面是我的代码:
User.kt
@Entity(tableName = "user_table")
data class User(
@PrimaryKey(autoGenerate = true)
val id:Long,
@Json(name = "name")
val uname:String,
val username:String,
val email:String,
@Embedded
val address: Address,
val phone:String,
val website:String,
@Embedded
val company: Company)
data class Address(
val street:String,
val suite:String,
val city:String,
val zipcode:String,
@Embedded
val geo: Geo)
data class Geo(
val lat:String,
val lng:String)
data class Company(
@Json(name = "name")
val companyName:String,
val catchPhrase:String,
val bs:String)
UserDao.kt
@Dao
interface UserDao{
@Query("select * from user_table")
fun getUserList():LiveData<List<User>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(userList:List<User>):List<Long>
}
UserRepository.kt
class UserRepository(private val userDao: UserDao) {
val userList: LiveData<List<User>> = userDao.getUserList()
suspend fun refreshUserList() {
withContext(Dispatchers.IO) {
val userList = UserApi.retrofitService.getUserData().await()
val list = userDao.insertAll(userList)
Log.e("list","${list.size}")
}
}
}
MainActivityViewModel.kt
class MainActivityViewModel(database:UserDao, application: Application) : AndroidViewModel(application){
private val userRepository = UserRepository(database)
val usersList = userRepository.userList
private var viewModelJob = Job()
private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main)
init {
getUsersList()
}
private fun getUsersList() {
coroutineScope.launch {
try{
userRepository.refreshUserList()
}catch (networkError: IOException){
Toast.makeText(getApplication(),"Failure",Toast.LENGTH_SHORT).show()
}
}
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
//Main View Model Destroys
}
}
UserAdapter.kt
class UserAdapter : RecyclerView.Adapter<UserAdapter.ViewHolder>(){
var userDetailsList:List<User> = emptyList()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(UserCellLayoutBinding.inflate(
LayoutInflater.from(parent.context)
))
}
override fun getItemCount(): Int {
return userDetailsList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val user = userDetailsList[position]
holder.bind(user)
}
class ViewHolder(private var binding: UserCellLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(user: User){
binding.user = user
binding.executePendingBindings()
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModelFactory: ViewModelFactory
private lateinit var viewModel: MainActivityViewModel
private var adapter:UserAdapter ?= null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val dataSource = UserRoomDatabase.getInstance(application).userDao
viewModelFactory = ViewModelFactory(dataSource,application)
viewModel = ViewModelProviders.of(this,viewModelFactory).get(MainActivityViewModel::class.java)
binding.lifecycleOwner = this
binding.mainActivityViewModel = viewModel
binding.executePendingBindings()
binding.userListRecyclerView.adapter = adapter
viewModel.usersList.observe(this, Observer<List<User>> {users ->
users?.apply {
adapter?.userDetailsList = users
}
})
}
}
任何帮助将不胜感激。
提前致谢。
【问题讨论】:
-
您是否尝试过在 usersList.observe 调用中设置断点? LiveData 永远不会更新吗?我也会使用类似 viewModel.usersList.observe(this, Observer { users -> users?.let { adapter?.userDetailsList = it } }) 而不是 apply
-
@bitjuggler 感谢您的回复,实时数据仅在第一次观察到之后才开始调试。也尝试像你一样观察列表,但仍然没有成功
-
您如何使用 Retrofit 使用 Json 响应?您的 addConverterFactory() 方法中有什么?调用 onResponse() 回调时的列表大小是多少?
-
@OmarBeshary 我使用 moshi 转换器工厂对对象进行反序列化。成功响应后,我将列表大小设为 10。这是api which I have consumed
-
我不确定这一点,但在 UserRepository.kt 中,您将 val userList 定义为 LiveData,然后在您的挂起乐趣中,您使用相同的变量名进行提取。也许这里有某种冲突?还有一件事:您只在插入后记录列表大小。您是否检查了 Long 列表是否正确产生 0、1、2、3,...,因为您使用的是 autoGenerate=true
标签: android kotlin android-room