У меня возникли проблемы с внедрением rxJava, чтобы проверить, есть ли подключение к Интернету на Android. Я делаю это так:
На моем запуске деятельности я имею это в onCreate:
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(); } } });
У меня есть класс Utils – это последний класс со статическими методами, которые используются в методе наблюдения:
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; } }
Я получаю android.os.NetworkOnMainThreadException, и я не могу найти почему, спасибо заранее.
Observable.just(...)
вызывается немедленно на вызывающей нити (в этом случае основной поток). Ваш код является фактически просто встроенной версией этого:
boolean activeConn = Utils.isActiveInternetConnection(Launcher.this); AndroidObservable.bindActivity(this, Observable.just(activeConn)) .subscribeOn(...) ...
Вы попытались переместить его из основного потока, вызвав subscribeOn()
– но вызов уже произошел.
То, как мы справляемся с этим (и я не уверен, что это лучший способ, но он работает) заключается в том, чтобы отложить сеть или заблокировать вызов до тех пор, пока не произойдет подписка, настройте наблюдаемое для запуска на правильные потоки и затем подписаться:
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(); } } });
Я предполагаю, just
просто вызывает метод синхронно, так как он ожидает логическое значение и пытается его получить.
Я довольно плохо RxJava
в RxJava
но вы можете попробовать что-то вроде этого:
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 -> {...});
Это мои данные из базы данных с помощью кода RXAndroid:
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)); } });
Я думаю, что just
оператор немедленно выдаст данные, поэтому нецелесообразно извлекать данные из базы данных через сеть. Он очень прост в использовании, но его можно использовать только для данных, которые уже находятся в мобильном телефоне.
У меня также была эта проблема, как у @Baniares, но после того, как я использую оператор create
, проблема исчезает …
Из документации RXJava:
static <T> Observable<T> create(Observable.OnSubscribe<T> f)
Возвращает Observable, который будет выполнять указанную функцию, когда подписчик подписывается на нее.
Использование оператора create
может установить стандартный процесс:
1 .subscribe(...)
Подписчик (подкласс класса Observer) начинает соединение с Observable.
2 .subscribeOn(Schedulers.io())
собирает обратную нить из RX-ThreadPool
3 .create(...)
извлекать данные с сервера … во время некоторого netWork..etc
4 .observeOn(AndroidSchedulers.mainThread())
это означает, что данные будут устанавливаться с помощью UI-Thread
5 Как только мы получим данные, мы можем установить данные в методе onNext () в .subscribe( )
, данные будут установлены в пользовательском интерфейсе UI-Thread, поскольку мы создаем UI-поток для работы с .observerOn(AndroidSchedulers.mainThread())
Цепочка методов просто не выполняется по порядку в коде.
Обратите внимание: если вы используете оператор .create (), вы должны закончить свое наблюдение в .create (), другой оператор, такой как map, flatMap не будет выполнен после оператора .create ().
AdamS является правильным, однако RxJava 2 теперь предлагает Observable.fromCallable () отложить наблюдаемую операцию до подписки. Хорошая ссылка: https://caster.io/lessons/fromcallable-converting-slow-methods-into-an-observable/
Пример кода примера из моего прецедента:
Single.fromCallable(new Callable<Response>() { @Override public Response call() throws Exception { return NetworkGateway.networkRequest(); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer);
Ваш метод isActiveInternetConnection
пытается подключиться к сети из основного потока приложения, попробуйте использовать обработчик или asynctask
для этого метода. Дополнительная информация об ошибке: Как исправить android.os.NetworkOnMainThreadException?