Android.os.NetworkOnMainThreadException usando rxjava en android
Estoy teniendo problemas para implementar rxJava con el fin de comprobar si hay conexión a Internet en android lo estoy haciendo así:
En mi actividad del lanzador tengo esto en onCreate:
- ¿Cómo utilizar Flowable en RxJava 2?
- Cancelación de varias suscripciones a la vez en RxAndroid - Android
- Suscribir 2 diferentes Observable y onNext ambos?
- RxAndroid: cambios de interfaz de usuario en el subproceso Schedulers.io ()
- Encadenamiento de servicios de Retrofit con soporte de RxJava
AndroidObservable.bindActivity(this, Observable.just(Utils.isActiveInternetConnection(Launcher.this))) .subscribeOn(Schedulers.newThread()) .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { if (aBoolean) { Toast.makeText(Launcher.this, "There is internet connection", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Launcher.this, "There is no internet connection", Toast.LENGTH_SHORT).show(); } } });
Tengo una clase Utils es una clase final con métodos estáticos los métodos en los que el observable está usando son los siguientes:
public static boolean isActiveInternetConnection(Context context) { if (isNetworkAvailable(context)) { try { HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection()); urlc.setRequestProperty("User-Agent", "Test"); urlc.setRequestProperty("Connection", "close"); urlc.setConnectTimeout(1500); urlc.connect(); return (urlc.getResponseCode() == 200); } catch (IOException e) { Log.e("network", "Error checking internet connection", e); } } else { Log.d("network", "No network available!"); } return false; } private static boolean isNetworkAvailable(Context context){ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); if (null != activeNetwork) { return true; } else { return false; } }
Estoy recibiendo android.os.NetworkOnMainThreadException y no puedo encontrar por qué, gracias de antemano.
- RxJava solo planificador de hilos de fondo
- RxJava / RxBinding: cómo manejar los errores en RxView
- ¿Cómo puedo implementar el equivalente RxJava de INotifyPropertyChanged para hacer un modelo de datos Observable?
- Comprensión de flujos de datos y múltiples suscriptores (con retroadaptación)
- Cómo utilizar rxandroid para escuchar la actualización de ubicación de gps
- Okhttp ignora la configuración de Dispatcher cuando se usa con Retrofit RxJavaCallAdapterFactory
- AsyncTask en RxJava
- Proguard y RxAndroid V1.1.0
Observable.just(...)
se llama inmediatamente en el hilo llamante (el hilo principal, en este caso). Su código es efectivamente sólo una versión en línea de este:
boolean activeConn = Utils.isActiveInternetConnection(Launcher.this); AndroidObservable.bindActivity(this, Observable.just(activeConn)) .subscribeOn(...) ...
Has intentado moverlo fuera del hilo principal llamando a subscribeOn()
– pero la llamada ya ha ocurrido.
La forma en que manejamos esto (y no estoy seguro de que sea la mejor manera, pero funciona) es aplazar la red o bloquear la llamada hasta que suceda la suscripción, configurar el observable para ejecutar en los hilos correctos y luego suscribirse:
AndroidObservable.bindActivity(this, Observable.defer(new Func0<Boolean>() { @Override public Observable<Observable<Boolean>> call() { return Observable.just(Utils.isActiveInternetConnection(Launcher.this)); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { if (aBoolean) { Toast.makeText(Launcher.this, "There is internet connection", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Launcher.this, "There is no internet connection", Toast.LENGTH_SHORT).show(); } } });
Supongo que just
llama al método de forma síncrona, ya que espera el valor booleano y trata de obtenerlo.
Soy algo malo en RxJava
pero usted puede intentar algo como esto:
Observable<Boolean> onlineObservable = Observable.create(new Observable.OnSubscribe<Boolean>() { @Override public void call(Subscriber subscriber) { subscriber.onNext(Utils.isActiveInternetConnection(context)); } }); onlineObservable.subscribeOn(Schedulers.newThread()).subscribe(result -> {...});
Este es mi recuperar datos de DataBase por RXAndroid código:
Observable.create(new Observable.OnSubscribe<List<GRO_VO>>() { @Override public void call(Subscriber<? super List<GRO_VO>> subscriber) { String jsonIn; jsonIn =retrieveDataFromDB(); Gson gson = new Gson(); Type listType = new TypeToken<List<GRO_VO>>() { }.getType(); eventJoinList = gson.fromJson(jsonIn, listType); Log.d("RX",jsonIn); subscriber.onNext(eventJoinList); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<List<GRO_VO>>() { @Override public void call(List<GRO_VO> eventJoinList) { Log.d("RX", ".subscribe"); recyclerView.setAdapter(new EventJoinAdapter(eventJoinList)); } });
Creo que el operador just
emitir datos inmediatamente, por lo que no es útil para recuperar los datos de una base de datos a través de la red. Es muy fácil de usar, pero sólo puede utilizarse para datos que ya están en el móvil.
También tuve ese problema, como @Baniares, pero después de usar el operador create
, el problema desaparece …
De la documentación de RXJava:
static <T> Observable<T> create(Observable.OnSubscribe<T> f)
Devuelve un Observable que ejecutará la función especificada cuando un Suscriptor se suscriba a ella.
El uso del operador create
puede establecer el proceso estándar:
1 .subscribe(...)
Subscriber (la subclase de la clase Observer) inicia la conexión a Observable.
2 .subscribeOn(Schedulers.io())
recopila un hilo de backGround desde el RX-ThreadPool
3 .create(...)
recuperar datos del servidor … durante algún netWork..etc
4 .observeOn(AndroidSchedulers.mainThread())
esto significa que los datos serán establecidos por el UI-Thread
5 Una vez que obtengamos los datos, podemos configurar los datos en el método onNext () en .subscribe( )
, los datos se establecerán en la interfaz de usuario por UI-Thread ya que hacemos el hilo de interfaz de usuario hacer el trabajo en el .observerOn(AndroidSchedulers.mainThread())
La cadena de métodos simplemente no ocurre por el orden en el código.
Y tenga en cuenta que si utiliza el operador .create (), debe haber terminado su observable en el .create (), otros operadores como map, flatMap no se ejecutará después del operador .create ().
AdamS es correcto, sin embargo RxJava 2 ahora ofrece Observable.fromCallable () para diferir una operación observable hasta la suscripción. Una buena referencia: https://caster.io/lessons/fromcallable-converting-slow-methods-into-an-observable/
Algunos ejemplos de código de mi caso de uso:
Single.fromCallable(new Callable<Response>() { @Override public Response call() throws Exception { return NetworkGateway.networkRequest(); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer);
Su método isActiveInternetConnection
tratando de conectarse a la red desde el hilo principal de la aplicación, trate de utilizar handler o asynctask
para este método Más información sobre el error: ¿Cómo arreglar android.os.NetworkOnMainThreadException?
- Implementar un indicador de actividad giratoria similar a iOS en Android
- Depuración de Android con Eclipse – sin puntos de interrupción