java - 当我检查网络状态时主线程卡住

标签 java android rx-java rx-android

这是我用于检查网络状态的 InternetUtil:

public class InternetUtil extends ContextWrapper {

    public InternetUtil(Context context) {
        super(context);
    }

    public static boolean isOnline(){
        ConnectivityManager cm = (ConnectivityManager) BaseApplication.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
        assert cm != null;
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (activeNetwork == null) return false;

        switch (activeNetwork.getType()) {
            case ConnectivityManager.TYPE_WIFI:
                if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                        activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                        isInternet())
                    return true;
                break;
            case ConnectivityManager.TYPE_MOBILE:
                if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                        activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                        isInternet())
                    return true;
                break;
            default:
                return false;
        }
        return false;
    }

    private static boolean isInternet() {

        Runtime runtime = Runtime.getRuntime();
        try {
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = ipProcess.waitFor();
            Log.d("", exitValue + "");
            return (exitValue == 0);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

        return false;
    }
}

这里我使用 Util:

if (InternetUtil.isOnline()) {
            BaseDataManager baseDataManager = new BaseDataManager(context);
            profileRepository = new ProfileRepository();

            Map<String, String> requestBody = new HashMap<>();
            requestBody.put(Constants.PHONE_KEY, phone);
            requestBody.put(Constants.PASSWORD_KEY, password);

            Observable.defer((Callable<ObservableSource<?>>) () -> baseDataManager.signIn(requestBody))
                    .subscribeOn(Schedulers.io())
                    .retryWhen(throwableObservable -> throwableObservable.flatMap((Function<Throwable, ObservableSource<?>>) throwable -> {
                        if (throwable instanceof HttpException) {
                            HttpException httpException = (HttpException) throwable;

                            if (httpException.code() == 401) {
                                return baseDataManager.refreshAccessToken();
                            }
                        }
                        return Observable.error(throwable);
                    }))
                    .subscribe(o -> {
                                if (o instanceof UserProfile) {
                                    UserProfile userProfile = (UserProfile) o;

                                    iLoginView.hideProgress();
                                    if (userProfile.getErrorDetails() != null) {
                                        iLoginView.onSigningInFailure(userProfile.getErrorDetails());
                                    } else {
                                        iLoginView.navigateToMainActivity();
                                        profileRepository.updateUserProfile(userProfile);
                                    }
                                }
                            },
                            throwable -> {
                                iLoginView.hideProgress();
                                iLoginView.onSigningInFailure(throwable.getMessage());
                            });

        } else {
            iLoginView.hideProgress();
            iLoginView.showOfflineMessage();
        }

如您所见,互联网状态检查在主线程中进行

但我想让它在不同的线程中工作。所以我想使用RXJava。

我尝试过这个,但我不知道如何使用这个Util:

public class InternetUtil {
    public static Observable<Boolean> isInternetOn(Context context) {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return Observable.just(activeNetworkInfo != null && activeNetworkInfo.isConnected());
    }
}

告诉我该怎么做?

最佳答案

您可以将之前的 inOnlike() 函数包装到 Observable 中。

public class InternetUtil {
    public static Observable<Boolean> isInternetOn() {
        return Observable.fromCallable(new Callable<Boolean>() {
            @Override
            public boolean call() throws Exception {
                return isOnline();
            }
        });
    }
}

然后你可以像这样使用它:

InternetUtil.isInternetOn()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe( new Action1<Boolean>() {
                @Override
                public void call(boolean isOnline) {
                    if(isOnline){
                    // your mainthread code here
                    }
                }
            });

如果你想使用flapMap,也许你可以使用这样的东西:

InternetUtil.isInternetOn()
            .flatMap((new Func1<Boolean, Observable<UserProfile>>() {
                @Override
                public Observable<UserProfile> call(boolean isOn) {
                    if (isOn){
                        return Observable.fromCallable((Callable<ObservableSource<?>>) () -> baseDataManager.signIn(requestBody));
                    } else {
                        return Obserable.error(new Throwable("no internet"));
                    }
                }
            })
            .retryWhen()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe()

关于java - 当我检查网络状态时主线程卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48030205/

相关文章:

java - 编写一个程序来读取未指定数量的整数

java - 线性数组的二叉树构造函数

java - Android - 图形显示在 Eclipse 中不工作

基于contentprovider数据变化的Android app widget更新

Android Observables.zip 列出可观察对象

java - 如何在RxJava中传输多个参数

Java 1.6 update 11 适用于 safari 5,但不适用于 java 1.6.25,为什么?

java - 舍入 BigDecimal 以匹配 C++ sprintf

android - 在同一进程中运行的两个应用程序是否可以具有不同的 STATIC 对象值?

java - 如何让 spring boot mvc 理解 observables?