12

I just upgraded to AndroidX and after doing that all my request. I make in background thread do not run but come up with this error.

private void getContactsList() {
    Task.callInBackground((Callable<Void>) () -> { 
     mainActivityViewModel.geContacts(contactListRequest).observe(MainActivity.this, new Observer<ContactListResponse>() {
            @Override
            public void onChanged(@Nullable ContactListResponse contactListResponse) {
                if(contactListRequest != null){
                    System.out.println("Successful");
                }
            }
        });
        return null;
    }).continueWith((Continuation<Void, Void>) task -> {
        if (task.isFaulted()) {
            Log.e(TAG, "find failed", task.getError());
        }
        return null;
    });
}



java.lang.IllegalStateException: Cannot invoke observe on a background thread
    at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:443)
    at androidx.lifecycle.LiveData.observe(LiveData.java:171)
    at com.qucoon.rubies.MainActivity.lambda$getContactsList$12(MainActivity.java:887)
    at com.qucoon.rubies.-$$Lambda$MainActivity$qPAxeGqyWT-wT3M7e8stM1rX2gQ.call(lambda)
    at bolts.Task$4.run(Task.java:357)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)
QuCoon Team
  • 121
  • 1
  • 1
  • 5
  • post your relevant code – Raghunandan Feb 15 '19 at 00:35
  • Ive done that @Raghunandan – QuCoon Team Feb 15 '19 at 00:37
  • 1
    Check your import of `Observer` and maybe from `MV` you should you `postValue(...)`? This method post from other thread and `setValue(...)` from the main thread. – ardiien Feb 15 '19 at 00:41
  • code looks fine. you need to post more relevant code. the threading part where you set contactList – Raghunandan Feb 15 '19 at 00:42
  • 1
    `Task.callInBackground((Callable) () ...` Maybe here hides the problem? **`Cannot invoke observe on a background thread`** – ardiien Feb 15 '19 at 00:52
  • It was working before i upgraded to Android X @YaroslavOvdiienko – QuCoon Team Feb 15 '19 at 01:04
  • if you are using viemodel and observing livedata that should happen on the main thread. if you want to get the contact list that should happen on a different thread. you would then postvalue to livedata and observere those changes in your activity. https://developer.android.com/topic/libraries/architecture/livedata – Raghunandan Feb 15 '19 at 03:17
  • @Raghunandan Yes thanks I applied what you said and it works fine – QuCoon Team Feb 15 '19 at 12:42

4 Answers4

16

You need to execute your code in the main thread try to call getContactsList() via a handler:

Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        public void run() {
            getContactsList()
        }
    });
robsiemb
  • 6,157
  • 7
  • 32
  • 46
Hamza Wakrim
  • 161
  • 1
  • 3
5

If for Kotlin and Coroutines (with AndroidX lifecycle library 2.2.0), the following might do:

lifecycleScope.launch {
   withContext(Dispatchers.Main) {
      // Do something
   }
}

Alternatively if not for lifecycleScope and the Lifecycle 2.2.0 library, you can define your own CoroutineScope and use it as so.

benChung
  • 366
  • 4
  • 9
  • Nice, this help me figure out my problem. You can also specified the dispatcher for launch builder `launch(Dispatchers.Main) {...}` because the default one without specified is `Dispatchers.Default`. – MohammadL Aug 27 '20 at 17:11
  • I had to add `implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.0"` to my build.gradle so that `lifecycleScope` became available in my lifecycleOwner component – hannojg Feb 27 '21 at 08:32
2

Annotate your test method with @UiThreadTest

Example:

@Test @UiThreadTest
fun test_onViewCreated() {
    val view = View(appContext)
    doNothing().`when`(spyObject).initEssentials(view)

    spyObject.onViewCreated(view, null)

    verify(spyObject).init(view)
}

This worked for me

0

java 11:

var handler = new Handler(Looper.getMainLooper());
    handler.post(() ->getContactsList());

lambdas are available in java 8 though. var is introduced in java 11.

Ryan
  • 356
  • 1
  • 6
  • 26