-2

I'm trying to make a network request using RxKotlin, but keep getting a NetworkOnMainThreadException I'm subscribing on the main thread, so I'm not sure why it's not taking it off of the UI thread.

Here is where I subscribe to the Observable

weatherInteractor.getWeather(lat, lng)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        {response ->
                            try {
                                val jsonData = response.body().string()
                                val currentWeather = getCurrentWeatherData(jsonData)
                                view!!.displayCurrentWeather(currentWeather)
                            } catch (e: JSONException) {
                                Log.d("Present JSON Exception", e.message)
                            } catch (e: IOException) {
                                Log.d("Present IO Exception", e.message)
                            }
                        },
                        {
                            error ->
                            error.printStackTrace()
                        }
                )
    }

Here is where I create my Observable

fun getWeather(lat: Double, lng: Double): Observable<Response> {
        val URL = ""
        val client = OkHttpClient()
        val request = Request.Builder()
                .url(URL)
                .build()

        return Observable.create { em ->
            try {
                val response = client.newCall(request).execute()
                em.onNext(response)
                em.onComplete()
            } catch (err: IOException) {
                err.printStackTrace()
                em.onError(err)
            }
        }
    }
Rafa
  • 3,219
  • 4
  • 38
  • 70

1 Answers1

1

It seems that you confuse subscribeOn and observeOn methods.

subscribeOn specifies the scheduler observable will be created on and will operate on. (You specify it once, position doesn't matter).

observeOn changes the scheduler for every action you type after it. You can use it multiple times and each set of actions will be executed on specified scheduler.

Here is an example:

Observable
            .just("test")
            .subscribeOn(Schedulers.io())
            .map(s -> { //this and all Observable code is executed on Schedulers.io()

                return s;
            })
            .observeOn(Schedulers.computation())
            .map(s -> { // executed on Schedulers.computation()

                return s;
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(s -> { // executed on Android main thread

            }, throwable -> {

            });
Amaksoft
  • 954
  • 9
  • 16
  • I'm not sure I'm seeing the difference. – Rafa Sep 28 '17 at 03:46
  • from your code: `weatherInteractor.getWeather(lat, lng) .observeOn(Schedulers.io()) .subscribeOn(AndroidSchedulers.mainThread())` You make request on `AndroidSchedulers.mainThread()` and code in `.subscribe()` (The `Observer`) runs on `Schedulers.io()` – Amaksoft Sep 28 '17 at 03:48
  • I see. I switched both of them, `subscribeOn(Schedulers.io())`, and `observeOn(AndroidSchedulers.mainThread())`, but it gives the same error – Rafa Sep 28 '17 at 03:54
  • Just tested the following code [see the gist](https://gist.github.com/amaksoft/9cdd14caffc1fd11f5de9b4e2d48cbf2) Worked exactly as intended (given android.permission.INTERNET in AndroidManifest.xml) – Amaksoft Sep 28 '17 at 04:21
  • I can upload the whole test project if needed – Amaksoft Sep 28 '17 at 04:22
  • could you please? At this point I think it may be something in my dependencies or how I set it up. – Rafa Sep 28 '17 at 16:29
  • Here you go: [example project](https://github.com/amaksoft/stackexchange-46459906) – Amaksoft Sep 28 '17 at 16:38
  • In the end, updating to okhttp3 was I think what did it. – Rafa Oct 03 '17 at 00:10