本人所在的项目中,由于历史原因,存在大量可以优化的地方,本文就网络状态这块,给出自己的一点思考。如果有更好的方法,可以评论告诉我。另外,网络状态这块以已经集成到我的基础库 CommonAndroid 中了,如果你对基础库的封装也有兴趣,也欢迎 star 或者 fork。
项目现状
- 已经有了 NetworkUtils 网络相关的工具类,包含了判断网络是否可用,获取当前网络类型等方法。
- 每个网络请求的方法之前都会先调用 NetworkUtils.isConnected(Context) 来检查网络
- 有几个 Activity 会注册网络变化的广播,从未联网到联网时自动刷新
一点思考
- 每次请求都判断网络能否简化,毕竟用户使用是一个连贯的过程,在网络状态没有变化时没有必要重复检查
- 多个 Activity 都注册几乎重复的广播能否优化,毕竟是重复劳动。
初步措施
- 使用单例模式,维护一个 NetStateReceiver 的广播接受者
- 使用观察者模式,让 NetStateReceiver 提供注册观察者的方法
- 当网络状态改变时,通知所有注册的观察者
具体实现
-
NetworkUtils 网络相关工具类
public enum NetworkType { NETWORK_WIFI, NETWORK_MOBILE, NETWORK_NONE } /** * 判断网络是否可用 */ public static boolean isConnected(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); return info != null && info.isConnected(); } /** * 获取当前网络类型 */ public static NetworkType getNetworkType(Context context) { NetworkType netType = NetworkType.NETWORK_NONE; ConnectivityManager cm = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); if (info != null && info.isAvailable()) { if (info.getType() == ConnectivityManager.TYPE_WIFI) { netType = NetworkType.NETWORK_WIFI; } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { netType = NetworkType.NETWORK_MOBILE; } } return netType; } -
NetChangeObserver 网络状态变化的观察者
public interface NetChangeObserver { void onConnect(NetworkType type); void onDisConnect(); } -
NetStateReceiver 网络状态变化的广播接受者
private ArrayList observers = new ArrayList<>(); /** * 注册网络连接观察者,可以注册多个观察者 */ public void registerObserver(NetChangeObserver observer) { if (observers == null) { observers = new ArrayList<>(); } observers.add(observer); } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equalsIgnoreCase(ANDROID_NET_CHANGE_ACTION)) { notifyObserver(context); } } private void notifyObserver(Context context) { for (int i = 0; i < observers.size(); i++) { NetChangeObserver observer = observers.get(i); if (observer != null) { boolean isConnected = NetworkUtils.isConnected(context); NetworkType currentType = NetworkUtils.getNetworkType(context); if (isConnected) { // 2/3/4G <--> WIFI 之间的网络切换, 也会进入此回调 observer.onConnect(currentType); } else { observer.onDisConnect(); } } } }使用建议
建议 Application 启动时,获取网络类型,并注册该 NetStateReceiver,Application 退出时,销毁该 Receiver
/** * 应用全局的网络变化处理 */ private void initNetChangeReceiver() { //获取当前网络类型 mNetType = NetworkUtils.getNetworkType(this); //定义网络状态的广播接受者 netStateReceiver = NetStateReceiver.getReceiver(); //给广播接受者注册一个观察者 netStateReceiver.registerObserver(netChangeObserver); //注册网络变化广播 NetworkUtils.registerNetStateReceiver(this, netStateReceiver); } private NetChangeObserver netChangeObserver = new NetChangeObserver() { @Override public void onConnect(NetworkUtils.NetworkType type) { if (type == mNetType) return; //net not change switch (type) { case NETWORK_WIFI: ToastUtils.showLong(this, "已切换到 WIFI 网络"); break; case NETWORK_MOBILE: ToastUtils.showLong(this, "已切换到 2G/3G/4G 网络"); break; } mNetType = type; } @Override public void onDisConnect() { ToastUtils.showShort(this, "网络已断开,请检查网络设置"); mNetType = NetworkUtils.NetworkType.NETWORK_NONE; } };
至此,项目中就可以根据 Application 的 mNetType 字段来判断网络是否可用,如果 Activity 需要 监听网络状态,只需要 NetStateReceiver.getReceiver().registerObserver(netChangeObserver) 来处理网络连解或者断开的情况。是不是感觉一下子整洁了不少。
再次提醒如果在 Activity 注册了一个 netChangeObserver,要在 onDestroy 时 移除掉,退出 应用时,移除所有 netChangeObserver,并解注册掉该广播。切记切记,完整代码可以去我的 GitHub 上查看,希望对你有帮助。知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 中国大陆许可协议进行许可。