本人所在的项目中,由于历史原因,存在大量可以优化的地方,本文就网络状态这块,给出自己的一点思考。如果有更好的方法,可以评论告诉我。另外,网络状态这块以已经集成到我的基础库 CommonAndroid 中了,如果你对基础库的封装也有兴趣,也欢迎 star 或者 fork。
项目现状
- 已经有了 NetworkUtils 网络相关的工具类,包含了判断网络是否可用,获取当前网络类型等方法。
- 每个网络请求的方法之前都会先调用 NetworkUtils.isConnected(Context) 来检查网络
- 有几个 Activity 会注册网络变化的广播,从未联网到联网时自动刷新
一点思考
- 每次请求都判断网络能否简化,毕竟用户使用是一个连贯的过程,在网络状态没有变化时没有必要重复检查
- 多个 Activity 都注册几乎重复的广播能否优化,毕竟是重复劳动。
初步措施
- 使用单例模式,维护一个 NetStateReceiver 的广播接受者
- 使用观察者模式,让 NetStateReceiver 提供注册观察者的方法
- 当网络状态改变时,通知所有注册的观察者
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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 网络状态变化的观察者
1 2 3 4 5 6 7 8
| public interface NetChangeObserver {
void onConnect(NetworkType type);
void onDisConnect();
}
|
- NetStateReceiver 网络状态变化的广播接受者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| private ArrayList<NetChangeObserver> 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) { observer.onConnect(currentType); } else { observer.onDisConnect(); } } }
}
|
使用建议
建议 Application 启动时,获取网络类型,并注册该 NetStateReceiver,Application 退出时,销毁该 Receiver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
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; 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 上查看,希望对你有帮助。
Title: 关于应用中网络状态变化的一点思考
Author: Jiandong
Date: 2017-01-19
Last Update: 2026-06-16
Blog Link: https://mjd507.github.io/2017/01/19/Network-States-Monitor/
Copyright Declaration: Please refer carefully, most of the content I have not fully mastered.