写点什么

飙车资深老教练 - 手撸一个 EventBus

作者:芝麻粒儿
  • 2022 年 7 月 13 日
  • 本文字数:5347 字

    阅读完需:约 18 分钟

飙车资深老教练-手撸一个EventBus

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!专注于 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); }
复制代码


这个时候基本的注册反注册就上线了,调用我们上面刚写的两个方法。


@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    initView();    EventCar.getInstance().add(this);} @Overrideprotected 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());} @Overrideprotected void onDestroy() {    EventCar.getInstance().remove(this);    super.onDestroy();} @Overridepublic 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

📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

发布于: 57 分钟前阅读数: 6
用户头像

芝麻粒儿

关注

尺有所短;寸有所长。 2020.08.29 加入

👑CSDN博客专家-华为云享专家-Android/Unity领域优质作者 🏅目前在模拟医学行业做Android/Unity双端开发 🏆微信公众号:【空名先生】 🏆QQ交流群:204918251或877807592

评论

发布
暂无评论
飙车资深老教练-手撸一个EventBus_android_芝麻粒儿_InfoQ写作社区