I'm trying to build an MVVM Kotlin app that uses Reactivex to make the Async calls to the API.
I've seen alot of threads with the same problem but on all of them the OP forgot to put the subscribeOn
in the call, in my code i do this and still have the network error. I've looked in the debugger to find the problem but to no succes.
class NoteViewModel(apiKey : String) : ViewModel () { // , Observable {
private lateinit var noteAdapter : NoteAdapter
private val notesList = MutableLiveData <ArrayList<Note>>()
private var subscription : Disposable
private val noteCollector = NoteCollector()
private val isLoading = MutableLiveData<Boolean>()
init {
subscription = noteCollector.getAll(apiKey)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { onCollectNotesStart() }
.doOnTerminate { onCollectNotesFinished() }
.subscribe(
{ result -> onCollectNotesSuccess(result) },
{ error -> onCollectNotesError(error) }
)
}
...
}
If you need more info let me know, i'll provide it.
EDIT: added stacktrace
E/AndroidRuntime: FATAL EXCEPTION: main
Process: jari.student.hogent.cominghome, PID: 2532
java.lang.RuntimeException: Unable to start activity ComponentInfo{jari.student.hogent.cominghome/jari.student.hogent.cominghome.Activities.MainActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2955)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:102)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)
at java.net.InetAddress.getAllByName(InetAddress.java:787)
at com.android.okhttp.Dns$1.lookup(Dns.java:39)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:200)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:148)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:90)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:190)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:142)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:104)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:410)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:343)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:489)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:262)
at com.github.kittinunf.fuel.toolbox.HttpClient.setBodyIfDoOutput(HttpClient.kt:91)
at com.github.kittinunf.fuel.toolbox.HttpClient.executeRequest(HttpClient.kt:39)
at com.github.kittinunf.fuel.core.requests.TaskRequest.call(TaskRequest.kt:14)
at com.github.kittinunf.fuel.core.DeserializableKt$response$result$1.invoke(Deserializable.kt:81)
at com.github.kittinunf.fuel.core.DeserializableKt$response$result$1.invoke(Unknown Source:0)
at com.github.kittinunf.result.Result$Companion.of(Result.kt:116)
at com.github.kittinunf.fuel.core.DeserializableKt.response(Deserializable.kt:81)
at com.github.kittinunf.fuel.core.Request.responseObject(Request.kt:344)
at jari.student.hogent.cominghome.Models.NoteCollector.getAll(NoteCollector.kt:22)
at jari.student.hogent.cominghome.ViewModels.NoteViewModel.<init>(NoteViewModel.kt:22)
at jari.student.hogent.cominghome.ViewModels.CustomViewModelFactory.create(CustomViewModelFactory.kt:11)
at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134)
at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102)
at jari.student.hogent.cominghome.Fragments.NoteFragment.onCreateView(NoteFragment.kt:27)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1340)
at android.app.Activity.performStart(Activity.java:7200)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2918)
... 9 more
EDIT 2: added getAll methode
override fun getAll(ApiKey: String): Observable<ArrayList<Note>> {
val bodyJson: JSONObject = JSONObject()
.put("apiKey", ApiKey)
val notesList: ArrayList<Note> = ArrayList()
val (_, _, result) = path.httpPost()
.header(mapOf("Content-Type" to "application/json"))
.body(bodyJson.toString())
.responseObject(Note.Deserializer())
val (notes, err) = result
if (err != null){
throw err.exception
}
notes?.forEach { note ->
notesList.add(note)
}
return Observable.fromArray(notesList)
}
Please change your getAll
implementation to this:
override fun getAll(ApiKey: String): Observable<ArrayList<Note>>
= Observable.create { emitter ->
val bodyJson: JSONObject = JSONObject()
.put("apiKey", ApiKey)
val notesList: ArrayList<Note> = ArrayList()
val (_, _, result) = path.httpPost()
.header(mapOf("Content-Type" to "application/json"))
.body(bodyJson.toString())
.responseObject(Note.Deserializer())
val (notes, err) = result
if (err != null) {
throw err.exception
}
notes?.forEach { note ->
notesList.add(note)
}
emitter.onNext(notesList)
}