在項目中老是會有須要判斷網絡狀態的地方,咱們經常使用的方法就是抽出一個工具類,我順手就是一個例:java
//判斷網絡是否可用 public static boolean isNetworkAvailable() { ConnectivityManager connectivityManager = (ConnectivityManager) getApplication() .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager == null) { return false; } NetworkInfo[] info = connectivityManager.getAllNetworkInfo(); if (info != null) { for (NetworkInfo networkInfo : info) { if (networkInfo.getState() == NetworkInfo.State.CONNECTED) { return true; } } } return false; }
細緻的你固然還會再寫一個判斷網絡類型的方法,反手再來一個例:android
//返回當前網絡類型 public static NetType getNetType() { ConnectivityManager connectivityManager = (ConnectivityManager) getApplication() .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager == null) { return NetType.NONE; } NetworkInfo info = connectivityManager.getActiveNetworkInfo(); if (info == null) { return NetType.NONE; } int type = info.getType(); if (type == ConnectivityManager.TYPE_MOBILE) { return NetType.MOBILE; } else if (type == ConnectivityManager.TYPE_WIFI) { return NetType.WIFI; } return NetType.NONE; }
而後就能夠在相應的操做前進行判斷網絡的判斷:api
if (NetworkUtils.isNetworkAvailable()) { doSomething(); } else { doSomething(); } if (NetworkUtils.getNetType()== xxx) { doSomething(); } else { doSomething(); }
1.首先最直觀的,不夠優雅,代碼判斷量太多,若是你的操做是須要頻繁的監聽網絡狀態,那麼過多的if/ else確定會讓後面維護變的眼花繚亂。
2.以上方法只能在網絡操做以前判斷網絡狀態,若用戶在網絡正常狀況下發起操做而中間改變網絡,好比下載中途忽然丟失網絡,則此時沒法作出相應的控制。
3.沒法只針對某種網絡類型進行監聽,好比只想監聽用戶切換到 WiFi 網絡時作出響應。
4.程序多處須要進行網絡監聽處理時,不能同時接收網絡變化,必須逐個地方手動處理。安全
接下來就是本文的重點,如何經過 NetStatusBus 這個庫來解決以上問題,讓你的網絡狀態監聽變得史無前例的簡單粗暴。網絡
implementation 'com.sunchen:netstatusbus:0.1.3' Application 中初始化 NetStatusBus: // 儘量早的進行這一步操做, 建議在 Application 中完成初始化操做 NetStatusBus.getInstance().init(this);
@Override public void onStart() { super.onStart(); NetStatusBus.getInstance().register(this); } @Override public void onStop() { super.onStop(); NetStatusBus.getInstance().unregister(this); }
@NetSubscribe(netType = NetType.AUTO) public void doSometing(NetType netType) { //netType 會返回當前的網絡類型爲 NetType.WIFI 仍是 NetType.MOBIL 或者 NetType.NONE Log.d(Constrants.LOG_TAG, netType.name()); }
到這裏就已經結束了,你的全部網絡操做已經均可以清晰優雅的在訂閱方法中進行處理了,固然你也能夠繼續往下看。ide
訂閱方法必須填寫一個NetType參數,能夠經過NetType的值來判斷當前網絡類型。工具
@NetSubscribe中 netType爲可選值,能夠設置訂閱的類型,可選值類型以下:性能
NetType.AUTOthis
這是默認值,任何網絡狀態發生變化,該類型訂閱者都會被回調。同時會傳入NetType參數告知你當前的網絡類型,示例以下:.net
//任何網絡狀態發生變化,該類型訂閱者都會被回調 @NetSubscribe(netType = NetType.AUTO) public void netChange(NetType netType) { Log.d(Constrants.LOG_TAG, netType.name()); } NetType.WIFI
只要當前是由 WIFI 改變引起的網絡狀態變化,該類型訂閱者都會被回調。同時會傳入NetType參數告知你當前的網絡類型,示例以下:
// 當 wifi 鏈接時,或者沒有網絡時會回調此方法 @NetSubscribe(netType = NetType.WIFI) public void netChange(NetType netType) { Log.d(Constrants.LOG_TAG, netType.name()); } NetType.MOBILE
只要當前是由移動網絡改變引起的網絡狀態變化,該類型訂閱者都會被回調。同時會傳入NetType參數告知你當前的網絡類型,示例以下:
// 當正在使用移動網絡時,或者沒有網絡時會回調此方法 @NetSubscribe(netType = NetType.MOBILE) public void netChange(NetType netType) { Log.d(Constrants.LOG_TAG, netType.name()); }
NetType.NONE
只有當網絡丟失時,該類型訂閱者纔會被回調。
// 只有當網絡丟失時,該類型訂閱者纔會被回調。 @NetSubscribe(netType = NetType.NONE) public void netChange(NetType netType) { Log.d(Constrants.LOG_TAG, netType.name()); }
有人會以爲,我用個庫爽就好了管它的原理幹什麼?
你放心,我只是小小的描述一下實現方式。
原理簡單來講,就是在全局初始化的時候就綁定對網絡的變化監聽。而後將進行註冊的父類全部的訂閱方法保存至集合中,這裏涉及到一些方法的校驗,最後在網絡狀態發生改變時利用 Java 反射機制遍歷執行全部訂閱方法。熟悉 EventBus 的小夥伴已經看出來了這裏借鑑了一小部分 EventBus 的思想。
回到第一步,那麼具體是如何綁定對網絡狀態變化的監聽呢?
之前咱們是經過註冊廣播來實現綁定網絡變動的監聽,在Android 7.0 之後,Google 基於性能和安全緣由對廣播進行了不少限制,好比監聽網絡變動的廣播 android.net.conn.CONNECTIVITY_CHANGE 使用靜態註冊的方式則沒法生效,而動態註冊的方式雖然能夠生效但畢竟不是最優解。
一樣出於性能和安全,以及擁抱變化的角度,最終咱們仍是使用官方推薦的方式,利用 ConnectivityManager.NetworkCallback 來進行網絡變化的監聽,這是在Android 5.0即android api 21推出的API,目前Android 5.0以上的市場佔有率在 85%以上,隨着國內各大廠商正在積極的推動適配普及Android Q,這個比例還會進一步增大,因此我的人認爲無需過於擔憂低版本適配。
總結
好的,這就關於 NetStatusBus 這個庫的內容,但願能夠幫助到須要的人。