網(wǎng)易云微專業(yè)安卓-即時網(wǎng)絡(luò)終結(jié)者蚂子,輕松駕馭Wifi與流量切換

文章純屬個人學(xué)習(xí)的代碼實現(xiàn)

網(wǎng)易云微專業(yè)公開課這節(jié)課主要講了監(jiān)聽網(wǎng)絡(luò)框架沃测,主要核心用的反射,好處是解耦食茎,還有一個好處是"專一",這個專一就是比如你想在不同網(wǎng)絡(luò)情況下做不同的動作蒂破,比如wifi的時候你選擇加載高清圖等,但是你在弱網(wǎng)或者3g别渔,4g只加載文本顯示這樣是不是挺好附迷。

1.核心還是利用廣播實現(xiàn)監(jiān)聽網(wǎng)絡(luò)變化,注冊廣播那些基本操作我們不介紹哎媚,我們講一下這個網(wǎng)絡(luò)變化事件分發(fā)喇伯,實現(xiàn)的原理有點像EventBus,就是利用收集的頁面類內(nèi)部包含我們需要處理的注解@Network的方法,然后把它存在一個HashMap上面
先看看代碼

public class NetStateReceiver extends BroadcastReceiver {
    private NetType netType;
    private Map<Object, List<MethodManager>> map;

    public NetStateReceiver() {
        netType = NetType.NONE;
        map = new HashMap<>();
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null||intent.getAction()==null) {
            Log.e("bigman","異常....");
            return;
        }
        if (intent.getAction().equalsIgnoreCase("android.net.conn.CONNECTIVITY_CHANGE")){
            Log.e("bigman","網(wǎng)絡(luò)發(fā)生了變化....");
            Application application = NetWorkManager.getDefault().getApplication();
            netType=NetworkUtils.getNetworkType(application);
            if(NetworkUtils.netIsConnected(application)){
                Log.e("bigman","網(wǎng)絡(luò)連接成功....");
            }else{
                Log.e("bigman","網(wǎng)絡(luò)連接失敗....");
            }
            post(netType);
        }
    }

這一段代碼實現(xiàn)了網(wǎng)絡(luò)變化的監(jiān)聽拨与,而分發(fā)方法post(netType);我們等一下再看

我們先看看稻据,這邊定一個了一個全局單例NetWorkManager,為啥先看這個類,因為他 是我們對外的接口

public class NetWorkManager {
    private static volatile NetWorkManager instance;
    private NetStateReceiver receiver;
    private Application application;

    public static NetWorkManager getDefault() {
        if(instance==null){
            synchronized (NetWorkManager.class){
                if (instance==null){
                    instance=new NetWorkManager();
                }
            }
        }
        return instance;
    }

    private NetWorkManager(){
         receiver = new NetStateReceiver();
    }

    public Application getApplication(){
        if (application==null){
            throw new RuntimeException("....");
        }
        return  application;
    }

    public void init(Application application){
        this.application=application;
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        application.registerReceiver(receiver,intentFilter);
    }

    public void register(Object object) {
        receiver.register(object);
    }
}

這一部分代碼主要完成了動態(tài)注冊廣播买喧,當(dāng)然我們還靜態(tài)注冊了捻悯,同學(xué)們可以自己去配置文件找找,這里用動態(tài)注冊的好處就是做到了很好的版本兼容淤毛,這里的核心方法是

    public void register(Object object) {
        receiver.register(object);
    }

這里調(diào)用了注冊了一個對象今缚,我們看看怎么調(diào)用的

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        NetWorkManager.getDefault().register(this);
    }
}

其實就是把當(dāng)前MainActivity對象傳給receiver(即NetStateReceiver)的register方法,這個register就完成了注解方法的收集钱床,我們看代碼

    public void register(Object object) {
        List<MethodManager> methodManagerList = map
                .get(object);
        if (methodManagerList == null) {
            methodManagerList = findAnnotationMethod(object);
            map.put(object, methodManagerList);
        }
    }

這里其實就是去遍歷類里面所有包含Network注解的方法荚斯,實現(xiàn)方法 是這個 findAnnotationMethod

 private List<MethodManager> findAnnotationMethod(Object object) {
        List<MethodManager> list = new ArrayList<>();
        Class<?> aClass = object.getClass();
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            Network annotation = method.getAnnotation(Network.class);
            if (annotation == null) {
                continue;
            }
            //獲取方法返回類型
//            method.getGenericReturnType();

            //獲取方法的參數(shù)
            Class<?>[] parameterTypes = method.getParameterTypes();

            if (parameterTypes.length != 1) {
                throw new RuntimeException("參數(shù)只能有一個");
            }
            MethodManager methodManager = new MethodManager(parameterTypes[0],annotation.netType(),method);
            list.add(methodManager);

        }
        return list;
    }

這個方法是核心也是反射的基本操作,首先通過 Object對象找到對應(yīng)的 Class對象查牌,然后通過這個 Class對象獲取所有的方法事期,然后遍歷所有方法,再通過Method方法 對象的method.getAnnotation(Network.class)方法 找到指定包含Network注解的方法纸颜,找到之后把該方法參數(shù)類型兽泣,注解的值和方法都包裝到這個MethodManager對象里面,然后再放進(jìn)HashMap存起來

好了胁孙,回到開始的地方唠倦,我們沒看的那個post事件分發(fā)称鳞,實現(xiàn) 代碼如下

 public  void post(NetType netType){
       if (map.isEmpty())return;
        Set<Object> set = map.keySet();
        for (Object getter : set) {
            List<MethodManager> methodManagerList = map.get(getter);
            if (methodManagerList!=null){
                for (MethodManager methodManager : methodManagerList) {
                    if (methodManager.getType().isAssignableFrom(netType.getClass())) {
                       switch (methodManager.getNetType()){
                           case AUTO:
                               invoke(methodManager,getter,netType);
                               break;
                           case WIFI:
                               if (netType==NetType.WIFI||netType==netType.NONE){
                                   invoke(methodManager,getter,netType);
                               }
                               break;
                           case CMNET:
                           case CMWAP:
                               if (netType==NetType.CMNET||netType==NetType.CMWAP||netType==netType.NONE){
                                   invoke(methodManager,getter,netType);
                               }
                               break;

                       }
                    }
                }
            }
        }
    }

這里其實原理就是通過key就是比如MainActivity對象找到上面register收集的帶Network注解的方法,然后通過invoke反射去調(diào)用稠鼻,這樣就實現(xiàn)了類似通知的效果

分析完后冈止,我們可以看到這個架構(gòu)方式,比我們以前寫接口監(jiān)聽候齿,代碼的解耦熙暴,職責(zé)的分配都簡潔很多,當(dāng)然見仁見智慌盯,這個方法不一定是最好的周霉,很多人不能容忍反射帶來的一丟丟性能。

大家想了解更多直接去我的github看代碼實現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亚皂,一起剝皮案震驚了整個濱河市俱箱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灭必,老刑警劉巖狞谱,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異厂财,居然都是意外死亡芋簿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門璃饱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來与斤,“玉大人,你說我怎么就攤上這事荚恶×么” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵谒撼,是天一觀的道長食寡。 經(jīng)常有香客問我,道長廓潜,這世上最難降的妖魔是什么抵皱? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮辩蛋,結(jié)果婚禮上呻畸,老公的妹妹穿的比我還像新娘。我一直安慰自己悼院,他們只是感情好伤为,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著据途,像睡著了一般绞愚。 火紅的嫁衣襯著肌膚如雪叙甸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天位衩,我揣著相機(jī)與錄音裆蒸,去河邊找鬼。 笑死蚂四,一個胖子當(dāng)著我的面吹牛光戈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遂赠,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼晌杰!你這毒婦竟也來了跷睦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肋演,失蹤者是張志新(化名)和其女友劉穎抑诸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體爹殊,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕乡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了梗夸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片层玲。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖反症,靈堂內(nèi)的尸體忽然破棺而出辛块,到底是詐尸還是另有隱情,我是刑警寧澤铅碍,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布润绵,位于F島的核電站,受9級特大地震影響胞谈,放射性物質(zhì)發(fā)生泄漏尘盼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一烦绳、第九天 我趴在偏房一處隱蔽的房頂上張望卿捎。 院中可真熱鬧,春花似錦爵嗅、人聲如沸娇澎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趟庄。三九已至括细,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戚啥,已是汗流浹背奋单。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留猫十,地道東北人览濒。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像拖云,于是被迫代替她去往敵國和親贷笛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 背景 如果遇到問題請在:http://www.reibang.com/p/301edd6a2e61討論Event...
    yjy239閱讀 828評論 0 1
  • EventBus的設(shè)計理念是基于觀察者模式的宙项,可以參考設(shè)計模式(1)—觀察者模式先來了解該設(shè)計模式乏苦。 1、程序示例...
    開發(fā)者如是說閱讀 870評論 0 5
  • EventBus是Guava的事件處理機(jī)制尤筐,是設(shè)計模式中的觀察者模式(生產(chǎn)/消費者編程模型)的優(yōu)雅實現(xiàn)汇荐。對于事件監(jiān)...
    tracy_668閱讀 5,871評論 0 5
  • 每個家庭都有可能出現(xiàn)一些沖突特別嚴(yán)重的場面,沖突出現(xiàn)中的家庭成員往往怒氣很大盆繁,處理這類事情需要一套特別的技...
    劉燦麗閱讀 707評論 0 3
  • 花了兩個晚上細(xì)看完秋葉和秦陽的《如何打造超級IP》掀淘,書對現(xiàn)在的一些IP現(xiàn)象解釋的非常透徹,其中最讓我覺得物超所值的...
    曾小梧閱讀 15,788評論 3 56