检查网络状态时主线程冻结

时间:2017-12-30 01:45:43

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

如您所见,Internet状态检查发生在主线程

但我想让它在另一个线程中工作。所以我想使用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());
    }
}

告诉我该怎么做?

1 个答案:

答案 0 :(得分:1)

您可以将之前的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()