[英]NetworkOnMainThreadException using rxjava android
I'm using rxjava2 to do a network call and I am getting the dreaded. 我正在使用rxjava2进行网络呼叫,但我感到恐惧。 NetworkOnMainThreadException.
NetworkOnMainThreadException。 I am using fromCallable, which should defer the call until subscription.
我正在使用fromCallable,它应该将呼叫推迟到订阅之前。 Here is my code:
这是我的代码:
override fun getMovie(movieId: Int) {
Single.fromCallable{getMovieFromAPI(movieId)}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { throwable -> Log.e(TAG, throwable.message) }
.unsubscribeOn(Schedulers.io())
.subscribe(object : SingleObserver<ArrayList<Movie>> {
override fun onSuccess(t: ArrayList<Movie>) {
view?.get()?.setMoviesActivityUIElements(t)
}
override fun onSubscribe(d: Disposable) {
compositeDisposable.add(d)
}
override fun onError(e: Throwable) {
Log.e(TAG,e.localizedMessage)
e.printStackTrace()
}
})
}
and my getMovieFromAPI(movieID): 和我的getMovieFromAPI(movieID):
fun getMovieFromAPI(movieId : Int) : ArrayList<Movie> {
val URL = Constants.API_URL + "/" + movieId
val httpURLConnection: HttpURLConnection
var movieList: ArrayList<Movie> = ArrayList()
val requestParam = RequestParam(Constants.GET_METHOD, URL)
requestParam.addParam(Constants.PARAM_LANGUAGE, Constants.PARAM_ENGLISH)
requestParam.addParam(Constants.PARAM_API_KEY, Constants.APIKey)
try {
httpURLConnection = requestParam.setUpConnection()
val statusCode = httpURLConnection.responseCode // <--error happens here
val stringBuilder = Movie.getResponse(httpURLConnection)
when (statusCode) {
HttpURLConnection.HTTP_OK -> movieList = Movie.parseMovie(stringBuilder.toString())
HttpURLConnection.HTTP_NOT_FOUND, HttpURLConnection.HTTP_UNAUTHORIZED -> {
view?.get()?.showError(statusCode)
errorMessage = Movie.errorMessage
movieList.clear()
}
else -> {
view?.get()?.showError(-1)
movieList.clear()
}
}
httpURLConnection.disconnect()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: JSONException) {
e.printStackTrace()
}
return movieList
}
Why is this happening? 为什么会这样呢? I looked at this question and it doesn't answer my question.
我看着这个问题 ,但没有回答我的问题。
EDIT Adding Log.e(TAG,Thread.currentThread().toString()) in the first line of getMovieFromAPI, 编辑在getMovieFromAPI的第一行中添加Log.e(TAG,Thread.currentThread()。toString()),
prints: Thread[main,5,main] 打印:线程[main,5,main]
07-06 06:49:55.882 1897-1897/com.webnation.imdb E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.webnation.imdb, PID: 1897
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.webnation.imdb/com.webnation.imdb.MovieDetailActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)
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:175)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:407)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:538)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(Unknown Source:0)
at com.webnation.imdb.presenter.MovieDetailPresenter.getMovieFromAPI(MovieDetailPresenter.kt:76)
at com.webnation.imdb.MovieDetailActivity.onCreate(MovieDetailActivity.kt:73)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
It's never a good idea to run network calls on the main thread. 在主线程上运行网络调用绝不是一个好主意。 Run it as an asynchronous task instead: Something like
而是将其作为异步任务运行:
private class MyTask extends AsyncTask<Void, Void, Integer> {
String textResult;
private final ProgressDialog mProgress = new ProgressDialog(SendMessageActivity.this);
String value;
int value2;
@Override
public void onPreExecute() {
mProgress.setMessage("Processing...");
mProgress.show();
}
@Override
protected Integer doInBackground(Void... params) {
val URL = Constants.API_URL + "/" + movieId
val httpURLConnection: HttpURLConnection
var movieList: ArrayList<Movie> = ArrayList()
val requestParam = RequestParam(Constants.GET_METHOD, URL)
requestParam.addParam(Constants.PARAM_LANGUAGE, Constants.PARAM_ENGLISH)
requestParam.addParam(Constants.PARAM_API_KEY, Constants.APIKey)
try {
httpURLConnection = requestParam.setUpConnection()
val statusCode = httpURLConnection.responseCode // <--error happens here
val stringBuilder = Movie.getResponse(httpURLConnection)
when (statusCode) {
HttpURLConnection.HTTP_OK -> movieList = Movie.parseMovie(stringBuilder.toString())
HttpURLConnection.HTTP_NOT_FOUND, HttpURLConnection.HTTP_UNAUTHORIZED -> {
view?.get()?.showError(statusCode)
errorMessage = Movie.errorMessage
movieList.clear()
}
else -> {
view?.get()?.showError(-1)
movieList.clear()
}
}
httpURLConnection.disconnect()
}
@Override
protected void onPostExecute(Integer result) {
mProgress.dismiss();
if (result==200){
//Put success message here
}
else {
}
super.onPostExecute(result);
}
}
Then call the AsyncTask in your main thread: 然后在您的主线程中调用AsyncTask:
new MyTask().execute(); 新的MyTask()。execute();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.