繁体   English   中英

android.os.NetworkOnMainThreadException在Android上使用rxjava

[英]android.os.NetworkOnMainThreadException using rxjava on android

我在执行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(...)在调用线程(在本例中为主线程Observable.just(...)上立即被调用。 您的代码实际上只是此代码的内联版本:

boolean activeConn = Utils.isActiveInternetConnection(Launcher.this);
AndroidObservable.bindActivity(this, 
        Observable.just(activeConn))
        .subscribeOn(...)
        ...

您已经尝试通过调用subscribeOn()将其移出主线程,但是该调用已经发生。

我们处理此问题的方法(并且我不确定这是否是最好的方法,但它是否有效)是将网络延迟或阻塞调用,直到订阅发生,将observable设置为在正确的线程上运行,然后订阅:

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();
                }
            }
        });

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);

我猜just同步调用该方法,因为它期望布尔值并尝试获取它。

我对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,当订阅者订阅该Observable时将执行指定的函数。

使用create运算符可以建立标准流程:

1 .subscribe(...)订阅服务器(Observer类的子类)启动与Observable的连接。

2 .subscribeOn(Schedulers.io())从RX-ThreadPool收集backGround线程

3 .create(...)在一些网络中从服务器中检索数据..etc

4 .observeOn(AndroidSchedulers.mainThread())这意味着数据将由UI-Thread设置

5一旦我们得到的数据,我们可以在该onNext()方法来设置数据.subscribe( )数据将通过UI线程的UI,因为我们做的UI线程设置上做的工作.observerOn(AndroidSchedulers.mainThread())

请注意,如果使用.create()运算符,则必须在.create()中完成可观察性,其他操作符(如map,flatMap)将不会在.create()运算符之后执行。

在开始使用RXJava / RXAndroid之前,我们必须了解一个非常重要的概念。 RX是一个基于回调的库,您告诉RX在什么条件下应该做什么,它调用您的传入函数(或者在JAVA中,我可能应该将它们称为匿名内部类...)来实现所需的功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM