java.lang.IllegalStateException: Cannot invoke observeForever on a background thread

前端 未结 3 616
梦谈多话
梦谈多话 2021-01-17 10:43

Can someone help me find where I am going wrong here. I need to continously observer network data and update the UI whenever there is a data change from the Worker. Please n

相关标签:
3条回答
  • 2021-01-17 10:53

    In another solution, you can call it from main dispatcher as

    GlobalScope.launch(Dispatchers.Main) {
      // your code here...
    }
    
    0 讨论(0)
  • 2021-01-17 10:57

    Additionally to the nice and detailled answer from @user1185087 here is a solution if you're using RxJava in your project. It's maybe not that short, but if you already use RxJava in your project, it's an elegant way to switch to the required thread (in this case the Android's UI thread via .observeOn(AndroidSchedulers.mainThread())).

    Observable.just(workManager.getStatusById(workRequest.getId()))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(status -> status.observeForever(workStatus -> {
            // Handling result on UI thread
        }), err -> Log.e(TAG, err.getMessage(), err));
    
    0 讨论(0)
  • 2021-01-17 11:09

    Change this:

    networkData.observeForever { newData->
        appExecutors.diskIO().execute {
            userDao.insert(newData.user)
        }
    }
    

    To:

    Variant B (with coroutines):

    GlobalScope.launch(Dispatchers.Main) { networkData.observerForever { /*..*/ } }
    

    But be aware, the usage of GlobalScope is not recommended: https://stackoverflow.com/a/54351785/1185087

    Variant A (without coroutines):

    Handler(Looper.getMainLooper()).post { networkData.observeForever{ /*..*/ } }
    

    Explanation

    Normally observe(..) and observeForever(..) should be called from the main thread because their callbacks (Observer<T>.onChanged(T t)) often change the UI which is only possible in the main thread. That's the reason why android checks if the call of the observe functions is done by the main thread.

    In your case UserRepository.init{} is called by a background thread, so the exception is thrown. To switch back to the main thread you can use one of the above variants. But be aware the code inside of your observe callback is executed by the main thread, too. Any expensive processing inside this callback will freeze your UI!

    0 讨论(0)
提交回复
热议问题