在 CoroutineWorker 中观察和更新 Room 数据库
Observe and update Room database within CoroutineWorker
我想将一些参数传递给 CoroutineWorker,使用此参数在我的房间数据库中进行查询,并将查询结果用于 运行 一个 url 连接(获取输入流).使用代码我可以在 Build window 中读到这个问题:“类型不匹配:推断的类型是 CoroutineScope 但 ViewModelStoreOwner 是预期的”。
UserDao
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun addUser(user: User)
@Update
suspend fun updateUser(user: User)
@Delete
suspend fun deleteUser(user: User)
@Query("SELECT * FROM user_table WHERE Name LIKE :name LIMIT 1")
fun selectUser(name: String): LiveData<User?>?
}
用户资料库
class UserRepository(private val userDao: UserDao) {
val readAllData: LiveData<List<User>> = userDao.readAllData()
suspend fun addUser(user: User){
userDao.addUser(user)
}
suspend fun updateUser(user:User){
userDao.updateUser(user)
}
suspend fun deleteUser(user: User){
userDao.deleteUser(user)
}
fun selectUser(name: String): LiveData<User?>? {
return userDao.selectUser(name)
}
}
UserViewModel
class UserViewModel(application: Application): AndroidViewModel(application) {
private val repository: UserRepository
fun addUser(user: User){
viewModelScope.launch(Dispatchers.IO) {
repository.addUser(user)
}
}
fun updateUser(user: User){
viewModelScope.launch(Dispatchers.IO){
repository.updateUser(user)
}
}
fun deleteUser(user: User){
viewModelScope.launch(Dispatchers.IO) {
repository.deleteUser(user)
}
}
fun selectUser(name: String): LiveData<User?>? {
return repository.selectUser(name)
}
}
这是工人:
class DownloadingWorker(context: Context,params:WorkerParameters) : CoroutineWorker(context, params) {
private lateinit var mUserViewModel: UserViewModel
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val Name = inputData.getString("Name")
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
val LiveDataSelectedUser = mUserViewModel.selectUser(name = Name)
LiveDataSelectedUser.observe(this, object : Observer<User?>(){
fun downloadfunction(@Nullable user: User?) {
val UserUrl = user.url
val url: URL? = try {
URL(UserUrl)
}catch (e: MalformedURLException){
Log.d("Exception", e.toString())
null
}
var list = mutableListOf<DownloadedData>()
url?.getStream()?.apply {
withContext(Dispatchers.Default){
list = parseDOM(this@apply) as MutableList<DownloadedData>
}}
//// then I would like to update user with the downloaded data
}} )
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
感谢您的建议
解决了从 Livedata 到 Data 的传递问题,并在 Coroutine 中使用 suspend fun。
在 UserDao 中:
@Query("SELECT * FROM user_table WHERE Name LIKE :name LIMIT 1")
suspend fun selectUser(name: String): List<User>
在存储库中:
suspend fun selectUser(name: String): List<User> {
return userDao.selectUser(name = name)
}
我可以在 worker 中以这种方式检索数据:
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val Name = inputData.getString("Name")
val database = getDatabase(applicationContext)
val repository = UserRepository(database.userDao())
return withContext(Dispatchers.IO){
try {
val user = repository.selectUser(name)
for(singleUser in user){
val UserUrl = singleUser.url
val url: URL? = try {
URL(UserUrl)
}catch (e: MalformedURLException){
Log.d("Exception", e.toString())
null
}
var list = mutableListOf<DownloadedData>()
url?.getStream()?.apply {
withContext(Dispatchers.Default){
list = parseDOM(this@apply) as MutableList<DownloadedData>
}}}
}
Result.success()
}catch (e: Exception){
Result.failure()
}
}
return Result.success()
}
}
也许这不是完美的解决方案,但它确实有效,希望对其他人有用。
我想将一些参数传递给 CoroutineWorker,使用此参数在我的房间数据库中进行查询,并将查询结果用于 运行 一个 url 连接(获取输入流).使用代码我可以在 Build window 中读到这个问题:“类型不匹配:推断的类型是 CoroutineScope 但 ViewModelStoreOwner 是预期的”。
UserDao
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun addUser(user: User)
@Update
suspend fun updateUser(user: User)
@Delete
suspend fun deleteUser(user: User)
@Query("SELECT * FROM user_table WHERE Name LIKE :name LIMIT 1")
fun selectUser(name: String): LiveData<User?>?
}
用户资料库
class UserRepository(private val userDao: UserDao) {
val readAllData: LiveData<List<User>> = userDao.readAllData()
suspend fun addUser(user: User){
userDao.addUser(user)
}
suspend fun updateUser(user:User){
userDao.updateUser(user)
}
suspend fun deleteUser(user: User){
userDao.deleteUser(user)
}
fun selectUser(name: String): LiveData<User?>? {
return userDao.selectUser(name)
}
}
UserViewModel
class UserViewModel(application: Application): AndroidViewModel(application) {
private val repository: UserRepository
fun addUser(user: User){
viewModelScope.launch(Dispatchers.IO) {
repository.addUser(user)
}
}
fun updateUser(user: User){
viewModelScope.launch(Dispatchers.IO){
repository.updateUser(user)
}
}
fun deleteUser(user: User){
viewModelScope.launch(Dispatchers.IO) {
repository.deleteUser(user)
}
}
fun selectUser(name: String): LiveData<User?>? {
return repository.selectUser(name)
}
}
这是工人:
class DownloadingWorker(context: Context,params:WorkerParameters) : CoroutineWorker(context, params) {
private lateinit var mUserViewModel: UserViewModel
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val Name = inputData.getString("Name")
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
val LiveDataSelectedUser = mUserViewModel.selectUser(name = Name)
LiveDataSelectedUser.observe(this, object : Observer<User?>(){
fun downloadfunction(@Nullable user: User?) {
val UserUrl = user.url
val url: URL? = try {
URL(UserUrl)
}catch (e: MalformedURLException){
Log.d("Exception", e.toString())
null
}
var list = mutableListOf<DownloadedData>()
url?.getStream()?.apply {
withContext(Dispatchers.Default){
list = parseDOM(this@apply) as MutableList<DownloadedData>
}}
//// then I would like to update user with the downloaded data
}} )
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
感谢您的建议
解决了从 Livedata 到 Data 的传递问题,并在 Coroutine 中使用 suspend fun。 在 UserDao 中:
@Query("SELECT * FROM user_table WHERE Name LIKE :name LIMIT 1")
suspend fun selectUser(name: String): List<User>
在存储库中:
suspend fun selectUser(name: String): List<User> {
return userDao.selectUser(name = name)
}
我可以在 worker 中以这种方式检索数据:
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val Name = inputData.getString("Name")
val database = getDatabase(applicationContext)
val repository = UserRepository(database.userDao())
return withContext(Dispatchers.IO){
try {
val user = repository.selectUser(name)
for(singleUser in user){
val UserUrl = singleUser.url
val url: URL? = try {
URL(UserUrl)
}catch (e: MalformedURLException){
Log.d("Exception", e.toString())
null
}
var list = mutableListOf<DownloadedData>()
url?.getStream()?.apply {
withContext(Dispatchers.Default){
list = parseDOM(this@apply) as MutableList<DownloadedData>
}}}
}
Result.success()
}catch (e: Exception){
Result.failure()
}
}
return Result.success()
}
}
也许这不是完美的解决方案,但它确实有效,希望对其他人有用。