【问题标题】:Data is inserted but wont retrieve using Room数据已插入,但不会使用 Room 检索
【发布时间】: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


【解决方案1】:

我忘记在 MainActivity.kt

中实例化适配器

适配器 = UserAdapter()

        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()

        adapter = UserAdapter()

        binding.userListRecyclerView.adapter = adapter

        viewModel.usersList.observe(this, Observer<List<User>> {users ->
            users?.apply {
                adapter?.userDetailsList = users
            }
        })

【讨论】:

    猜你喜欢
    • 2021-02-12
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多