I would like to pass some parameters to a CoroutineWorker, make a query in my room database using this parameter and use the result of the query to run an url connection (obtaining an inputstream). Using the code I can read this problem in Build window: "Type mismatch: inferred type is CoroutineScope but ViewModelStoreOwner was expected".
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?>?
}
UserRepository
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)
}
}
and this is the worker:
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()
}
}
}
Thank you for your suggestions
Solved passing from Livedata to Data with suspend fun in Coroutine. In UserDao:
@Query("SELECT * FROM user_table WHERE Name LIKE :name LIMIT 1")
suspend fun selectUser(name: String): List<User>
In Repository:
suspend fun selectUser(name: String): List<User> {
return userDao.selectUser(name = name)
}
In the worker I can retrieve data in this manner:
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()
}
}
Maybe it is not the perfect solution, but it works and hopefully it will be useful for someone else.