Home > database >  kotlin coroutines trying to build recipes app based on recipessdb with kotlin coroutines and mvvm b
kotlin coroutines trying to build recipes app based on recipessdb with kotlin coroutines and mvvm b

Time:07-24

here is my api sevice

 interface GetDataServices {
        @GET("categories.php")
        suspend fun getCategoryList(): Category

here is my Repositor

class Repository(
    var getDataService : GetDataServices ?=null,
    var dao: RecipeDao?=null,
    var application: Application
){

    //-1-get Main category from api
     suspend fun getMainCategory(): Category? {
         var res_rep= getDataService?.getCategoryList()
        return res_rep
        Log.v("res_rep_get",res_rep.toString())
     }
}

here is my ViewModel

class CategoryViewModel: ViewModel(){
    var repository:Repository?=null

    var  mainCategoryList:MutableLiveData<ArrayList<CategoryItems>?>?=MutableLiveData()

    suspend fun getMainCategory(){
    viewModelScope.launch(Dispatchers.IO) {
        val result= withContext(Dispatchers.Main){

            repository?.getMainCategory()

        }
        mainCategoryList!!.value = result!!.categoriesitems as ArrayList<CategoryItems>?


    }
    }

}

here is my activity

@OptIn(DelicateCoroutinesApi::class)
class SplashActivity : BaseActivity(), EasyPermissions.RationaleCallbacks,
    EasyPermissions.PermissionCallbacks {

    private var READ_STORAGE_PERM = 123
    lateinit var categoryViewModel: CategoryViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        GlobalScope.launch {
          //  readStorageTask()
            withContext(Dispatchers.Main){
                getCategories()
            }

        }
        
    }


    suspend fun getCategories() {
        categoryViewModel = ViewModelProvider(this).get(CategoryViewModel::class.java)

        categoryViewModel!!.getMainCategory()

        categoryViewModel.mainCategoryList?.observe(this) { value ->
            value?.let {
                Log.d("cor_get", value.toString())
            }
        }

    }

here isُError

  com.example.foodrecipeapp.viewmodel.CategoryViewModel$getMainCategory$2.invokeSuspend(CategoryViewModel.kt:26)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)

here isُ another Error

    at com.example.foodrecipeapp.viewmodel.CategoryViewModel$getMainCategory$2.invokeSuspend(CategoryViewModel.kt:26)

here is my dependincies

def lifecycle_version = "2.5.0-alpha01" def arch_version = "2.1.0" implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version") // ViewModel utilities for Compose implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") // LiveData implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")

kapt("androidx.lifecycle:lifecycle-compiler:2.5.0")

CodePudding user response:

  1. You're doing your api request from the main thread

    val result = withContext(Dispatchers.Main) { repository?.getMainCategory() }

Just leave it as

val result = repository?.getMainCategory()

I would guess that you're receiving an error from Retrofit about sending requests from the main thread.

  1. You have too many wrappers withContext(), you don't need them.
  2. You shouldn't use GlobalScope.launch for such cases as in your SplashActivity. Just operate viewModelScope and that would be enough.
  3. Add a brief error handling. result!!.categoriesitems will always fail if your server returns any http error or there is no internet connection

Please also take a look here. It has a great explanation about using scopes and creating coroutines.

CodePudding user response:

var repository is declared but not instantiated.

class CategoryViewModel: ViewModel(){
        /*
         *Declared but not instantiated
         */
        var repository:Repository?=null
    
        var  mainCategoryList:MutableLiveData<ArrayList<CategoryItems>?>?=MutableLiveData()
    
        suspend fun getMainCategory(){
        viewModelScope.launch(Dispatchers.IO) {
            val result= withContext(Dispatchers.Main){
    
                repository?.getMainCategory()
    
            }
            mainCategoryList!!.value = result!!.categoriesitems as ArrayList<CategoryItems>?
    
    
        }
        }
    
    }
  • Related