文章纯属个人学习的代码实现
网易云微专业公开课这节课主要讲了监听网络框架,主要核心用的反射,好处是解耦,还有一个好处是"专一",这个专一就是比如你想在不同网络情况下做不同的动作,比如
wifi
的时候你选择加载高清图等,但是你在弱网
或者3g,4g
只加载文本显示这样是不是挺好。
1.核心还是利用广播实现监听网络变化,注册广播那些基本操作我们不介绍,我们讲一下这个网络变化事件分发,实现的原理有点像EventBus
,就是利用收集的页面类内部包含我们需要处理的注解@Network
的方法,然后把它存在一个HashMap
上面
先看看代码
public class NetStateReceiver extends BroadcastReceiver {
private NetType netType;
private Map
这一段代码实现了网络变化的监听,而分发方法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);
}
}
这一部分代码主要完成了动态注册广播,当然我们还静态注册了,同学们可以自己去配置文件找找,这里用动态注册的好处就是做到了很好的版本兼容,这里的核心方法是
public void register(Object object) {
receiver.register(object);
}
这里调用了注册了一个对象,我们看看怎么调用的
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NetWorkManager.getDefault().register(this);
}
}
其实就是把当前MainActivity
对象传给receiver
(即NetStateReceiver
)的register
方法,这个register
就完成了注解方法的收集,我们看代码
public void register(Object object) {
List methodManagerList = map
.get(object);
if (methodManagerList == null) {
methodManagerList = findAnnotationMethod(object);
map.put(object, methodManagerList);
}
}
这里其实就是去遍历类里面所有包含Network
注解的方法,实现方法 是这个 findAnnotationMethod
private List findAnnotationMethod(Object object) {
List 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();
//获取方法的参数
Class>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
throw new RuntimeException("参数只能有一个");
}
MethodManager methodManager = new MethodManager(parameterTypes[0],annotation.netType(),method);
list.add(methodManager);
}
return list;
}
这个方法是核心也是反射的基本操作,首先通过 Object
对象找到对应的 Class
对象,然后通过这个 Class
对象获取所有的方法,然后遍历所有方法,再通过Method
方法 对象的method.getAnnotation(Network.class)
方法 找到指定包含Network
注解的方法,找到之后把该方法参数类型,注解的值和方法都包装到这个MethodManager
对象里面,然后再放进HashMap
存起来
好了,回到开始的地方,我们没看的那个post
事件分发,实现 代码如下
public void post(NetType netType){
if (map.isEmpty())return;
Set
这里其实原理就是通过key
就是比如MainActivity
对象找到上面register
收集的带Network
注解的方法,然后通过invoke
反射去调用,这样就实现了类似通知的效果
分析完后,我们可以看到这个架构方式,比我们以前写接口监听,代码的解耦,职责的分配都简洁很多,当然见仁见智,这个方法不一定是最好的,很多人不能容忍反射带来的一丢丢性能。
大家想了解更多直接去我的github看代码实现