在Android开发过程中,很多时候都会用到当前网络的状态判断以及网络状况发生变化的时候做出相应的反应,要想监听网络状态,用观察者模式再合适不过了,废话不多说,直接上代码。
观察者模式属于面向对象的23中设计模式之一,不了解的同学请自行Google
既然用观察者模式,自然离不开观察者模式里最重要的两个类Subject和Ovserver了
Subjcet接口:
/**
* Description: observer subject
* author: Wang
* date: 11/28/16 11:19 AM
*
* Copyright©2016 by wang. All rights reserved.
*/
public interface NetConnectionSubject {
/**
* 注册观察者
*
* @param observer
*/
public void addNetObserver(NetConnectionObserver observer);
/**
* 移除观察者
*
* @param observer
*/
public void removeNetObserver(NetConnectionObserver observer);
/**
* 状态更新通知
*
* @param type
*/
public void notifyNetObserver(int type);
}
Observer接口:
/**
* Description: observer
* author: Wang
* date: 11/28/16 11:20 AM
*
* Copyright©2016 by wang. All rights reserved.
*/
public interface NetConnectionObserver {
/**
* 通知观察者更改状态
*
* @param type
*/
public void updateNetStatus(int type);
}
在Android里,最适合实现Subject类的,莫过于Application了,因为它全局唯一而且生命周期就是这个App的生命周期:
/**
* Description: App's application should extend this class
* author: Wang
* date: 11/28/16 10:34 AM
*
* Copyright©2016 by wang. All rights reserved.
*/
public abstract class BaseApplication extends Application implements NetConnectionSubject {
protected static BaseApplication instance;
private int currentNetType = -1;
private List observers = new ArrayList<>();
public static BaseApplication getInstance() {
return instance;
}
/**
* current net connection type
*
* @return
*/
public int getCurrentNetType() {
return currentNetType;
}
/**
* current net connection status
*
* @return
*/
public boolean isNetConnection() {
return currentNetType == NetWorkUtil.NET_NO_CONNECTION ? false : true;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
currentNetType = NetWorkUtil.getConnectionType(this);
}
@Override
public void addNetObserver(NetConnectionObserver observer) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
@Override
public void removeNetObserver(NetConnectionObserver observer) {
if (observers != null && observers.contains(observer)) {
observers.remove(observer);
}
}
@Override
public void notifyNetObserver(int type) {
/**
* 避免多次发送相同的网络状态
*/
if (currentNetType == type) {
return;
} else {
currentNetType = type;
if (observers != null && observers.size() > 0) {
for (NetConnectionObserver observer : observers) {
observer.updateNetStatus(type);
}
}
}
}
}
具体谁要实现Observer接口,就要看具体场景了,这里以Activity为栗子吧:
/**
* Description: TODO
* author: WangKunHui
* date: 16/12/30 下午3:08
*
* Copyright©2016 by wang. All rights reserved.
*/
public class TestActivity extends Activity implements NetConnectionObserver {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**省略一些方法**/
BaseApplication.getInstance().addNetObserver(this);
}
@Override
public void updateNetStatus(int type) {
//当监听网络状态发生变化 这里会及时的收到回馈
}
@Override
protected void onDestroy() {
super.onDestroy();
BaseApplication.getInstance().removeNetObserver(this);
}
}
这里有个地方一定要注意:当Activity销毁的时候,一定要把这个观察者从观察者队列里移除掉!否者会发生内存泄漏
到这里,观察者模式已经写完了,谢谢收看。
读者:你是不是忘了点什么,说好的网络监听呢?
我:Easy easy~ 刚刚只不过是中场休息
如果只有上面那么多的话,是不能监听网络状态的,想要监听网络状态的变化,还得靠我们的广播接收者啊,有请:
/**
* Description: 网络连接状态的监听
* author: Wang
* date: 16/8/3 下午10:54
*
* Copyright©2016 by wang. All rights reserved.
*/
public class NetConnectionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
int connectionType = NetWorkUtil.getConnectionType(context);
/**
* 更改网络状态
*/
if (BaseApplication.getInstance() != null) {
BaseApplication.getInstance().notifyNetObserver(connectionType);
}
}
}
}
NetWorkUtil:
/**
* @author Wang
* @version 1.0.0
* @description 网络操作工具类
* @create 2014-2-18 上午09:22:30
* @company
*/
public class NetWorkUtil {
/**
* 无网络链接
*/
public static final int NET_NO_CONNECTION = 0;
/**
* wifi
*/
public static final int NET_TYPE_WIFI = 1;
public static final int NET_TYPE_2G = 2;
public static final int NET_TYPE_3G = 3;
public static final int NET_TYPE_4G = 4;
/**
* 未知的网络类型
*/
public static final int NET_TYPE_UNKNOWN = 5;
/**
* 获取网络类型
*
* @param context
* @return
*/
public static int getConnectionType(Context context) {
int netType = NET_NO_CONNECTION;
NetworkInfo networkInfo = ((ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
if (networkInfo == null) {
netType = NET_NO_CONNECTION;
} else {
if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
netType = NET_TYPE_WIFI;
} else {
int networkType = networkInfo.getSubtype();
switch (networkType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
netType = NET_TYPE_2G;
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9:replace by 14
case TelephonyManager.NETWORK_TYPE_EHRPD: //api<11:replace by 12
case TelephonyManager.NETWORK_TYPE_HSPAP: //api<13:replace by 15
netType = NET_TYPE_3G;
break;
case TelephonyManager.NETWORK_TYPE_LTE: //api<11:replace by 13
netType = NET_TYPE_4G;
break;
default:
String subType = networkInfo.getSubtypeName();
if (subType.equalsIgnoreCase("TD-SCDMA") ||
subType.equalsIgnoreCase("WCDMA") ||
subType.equalsIgnoreCase("CDMA2000")) {
netType = NET_TYPE_3G;
} else {
netType = NET_TYPE_UNKNOWN;
}
break;
}
}
}
return netType;
}
}
好了,到这里,标题上所有的内容已经写完了,最后,别忘了权限和注册广播接收者。
如有错误,欢迎指正。
如有有用,随手点个赞呗亲~