飙车资深老教练 - 手撸一个 EventBus
- 2022 年 7 月 13 日
本文字数:5347 字
阅读完需:约 18 分钟
👉关于作者
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!专注于 Android/Unity 和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
👉即将学会
经过前面两节内容学习,我们已经学会了 EventBus 很多的内容,今天小空带你自己手撸一个这种框架。
👉背景
🙈小空(坏笑):小芝,昨天和前天的内容学习的怎么样啦。
🙎小芝(😝):还用说吗,肯定没学会啊。
🙈小空(😎):好,今天我们继续,直接自己写一个类似框架。
🙎小芝(😥):等等,我说的是没学会啊。啊?
👉实践过程
基本的反射调用
首先是事件总线的工具类,我们需要管理的有很多,所以有必要泛型一下
public static EventCar eventCar;
private EventCar() {
}
单例完,就是 add,remove 等类似注册解注册的方法了,因为需要 Activity/Fragment 等类型,所以使用 obj 类型合适
private ArrayList<Object> objects = new ArrayList<Object>();
public void add(Object object){
objects.add(object);
}
public void remove(Object object){
objects.remove(object);
}
这个时候基本的注册反注册就上线了,调用我们上面刚写的两个方法。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
EventCar.getInstance().add(this);
}
@Override
protected void onDestroy() {
EventCar.getInstance().remove(this);
super.onDestroy();
}
小关键来了,这个时候函数的反射调用要上了,因为不止 Activity,所以我们要将里面分清楚
public void post(T obj) {
for (Object object : objects) { //在这区分了activity fragment等
if (object instanceof Activity) {
Activity activity= (Activity) object;
Class<? extends Activity> cls =activity.getClass();
try {
Method declaredMethod = cls.getDeclaredMethod("receive", obj.getClass()); //""内的方法名之自定的
declaredMethod.invoke(activity, (Object) obj);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
好了,我们小小的实验一下。看看能否出现效果
public void receive(MessageEvent msg) {
Log.e("TAG","接受到了消息"+msg.getName());
}
@Override
protected void onDestroy() {
EventCar.getInstance().remove(this);
super.onDestroy();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.ceshi:
EventCar.getInstance().post(new MessageEvent("空名先生"));
break;
}
}
运行,结果出现
恩,效果可看,让我们继续的深入。
指定接收线程
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Process {
int value() default 0;
}
我们调用一下看看
@Process(EventCar.SubThread) //内容在EventCar中有定义
public void receive(MessageEvent msg) {
Log.e("TAG","接受到了消息"+msg.getName());
}
回到 EventCar 中补全逻辑
final Method declaredMethod = cls.getDeclaredMethod("receive", obj.getClass()); //""内的方法名之自定的
Annotation[] annotations = declaredMethod.getAnnotations();
for(Annotation annotation : annotations){ //因为类可能不止一个标记 ,遍历获得对应的Process标记注解
if(annotation.annotationType() == Process.class){
Process process = (Process)annotation;
value = process.value();
}
}
if(value == MainThread){
activity.runOnUiThread(new Runnable() { //在ui线程
@Override
public void run() {
try {
declaredMethod.invoke(activity, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}else if(value == SubThread){
new Thread(new Runnable() { //如果在子线程的话
@Override
public void run() {
try {
declaredMethod.invoke(activity, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}).start();
}
去测试下,咦,还是没问题;
好,满足了 activity 的 就该有 fragment/activity/service 各种交叉通信,这也是上面我们使用泛型和 obj 类型的原因
最终修补完善 EventCar:
public void post(final T obj) {
for (Object object : objects) { //在这区分了activity fragment等
int value = 0;
if (object instanceof Activity) {
final Activity activity = (Activity) object;
Class<? extends Activity> cls = activity.getClass();
try {
final Method declaredMethod = cls.getDeclaredMethod("receive", obj.getClass()); //""内的方法名之自定的
Annotation[] annotations = declaredMethod.getAnnotations();
for (Annotation annotation : annotations) { //因为类可能不止一个标记 ,遍历获得对应的Process标记注解
if (annotation.annotationType() == Process.class) {
Process process = (Process) annotation;
value = process.value();
}
}
if (value == MainThread) {
activity.runOnUiThread(new Runnable() { //在ui线程
@Override
public void run() {
try {
declaredMethod.invoke(activity, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
} else if (value == SubThread) {
new Thread(new Runnable() { //如果在子线程的话
@Override
public void run() {
try {
declaredMethod.invoke(activity, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
} else if (object instanceof Fragment) {
final Fragment fragment = (Fragment) object;
Class<? extends Fragment> cls = fragment.getClass();
try {
final Method declaredMethod = cls.getDeclaredMethod("receive", obj.getClass());
Annotation[] annotations = declaredMethod.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation.annotationType() == Process.class) {
Process process = (Process) annotation;
value = process.value();
}
}
if (value == MainThread) {
fragment.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
try {
declaredMethod.invoke(fragment, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
} else if (value == SubThread) {
new Thread(new Runnable() {
@Override
public void run() {
try {
declaredMethod.invoke(fragment, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
} else if (object instanceof Service) {
final Service service = (Service) object;
Class<? extends Service> cls = service.getClass();
try {
final Method declaredMethod = cls.getDeclaredMethod("receive", obj.getClass());
Annotation[] annotations = declaredMethod.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation.annotationType() == Process.class) {
Process process = (Process) annotation;
value = process.value();
}
}
if (value == MainThread) {
try {
declaredMethod.invoke(service, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else if (value == SubThread) {
new Thread(new Runnable() {
@Override
public void run() {
try {
declaredMethod.invoke(service, (Object) obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
👉其他
📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://www.infoq.cn/profile/DB2492B85795C4/publish
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。
版权声明: 本文为 InfoQ 作者【芝麻粒儿】的原创文章。
原文链接:【http://xie.infoq.cn/article/79c3d57958f02ace970f32e40】。文章转载请联系作者。
芝麻粒儿
尺有所短;寸有所长。 2020.08.29 加入
👑CSDN博客专家-华为云享专家-Android/Unity领域优质作者 🏅目前在模拟医学行业做Android/Unity双端开发 🏆微信公众号:【空名先生】 🏆QQ交流群:204918251或877807592
评论