做视频网站要什么格式中信建设有限责任公司官网英文

当前位置: 首页 > news >正文

做视频网站要什么格式,中信建设有限责任公司官网英文,wordpress能静态吗,做淘宝必备网站整体流程阅读 EventBus在使用的时候基本分为以下几步#xff1a; 1、注册订阅者 EventBus.getDefault().register(this);2、订阅者解注册#xff0c;否者会导致内存泄漏 EventBus.getDefault().unregister(this);3、在订阅者中编写注解为Subscribe的事件处理函数 Subscri…整体流程阅读 EventBus在使用的时候基本分为以下几步 1、注册订阅者 EventBus.getDefault().register(this);2、订阅者解注册否者会导致内存泄漏 EventBus.getDefault().unregister(this);3、在订阅者中编写注解为Subscribe的事件处理函数 Subscribe(threadMode ThreadMode.MAIN, sticky true, priority 1) public void onMsgEventReceived(MsgEvent event) {Toast.makeText(this, event.getMsg(), Toast.LENGTH_LONG).show(); }4、事件发送 EventBus.getDefault().post(msg1 - coming);我们先按使用的流程大体看下源码逻辑源码版本3.3.1 注册源码逻辑 public static EventBus getDefault() {EventBus instance defaultInstance;if (instance null) {synchronized (EventBus.class) {instance EventBus.defaultInstance;if (instance null) {instance EventBus.defaultInstance new EventBus();}}}return instance;}EventBus 使用了双重校验锁的单例设计模式保证用到的对象是唯一的首次使用对象为空的时候通过下面构造创建一个。 public EventBus() {this(DEFAULT_BUILDER);}DEFAULT_BUILDER是一个final常量在加载的时候就进行初始化赋一个EventBusBuilder对象如下面代码所示。 private static final EventBusBuilder DEFAULT_BUILDER new EventBusBuilder();EventBusBuilder是EventBus的建造类里面参数在加载的时候进行了初始化。 public class EventBusBuilder {private final static ExecutorService DEFAULT_EXECUTOR_SERVICE Executors.newCachedThreadPool();boolean logSubscriberExceptions true;boolean logNoSubscriberMessages true;boolean sendSubscriberExceptionEvent true;boolean sendNoSubscriberEvent true;boolean throwSubscriberException;boolean eventInheritance true;boolean ignoreGeneratedIndex;boolean strictMethodVerification;ExecutorService executorService DEFAULT_EXECUTOR_SERVICE;ListClass? skipMethodVerificationForClasses;ListSubscriberInfoIndex subscriberInfoIndexes;Logger logger;MainThreadSupport mainThreadSupport;… }如果有需要的话我们也可以通过配置EventBusBuilder来更改EventBus的属性在EventBus中有一个静态方法直接返回一直新的EventBusBuilder对象设置完参数后调用build()来以新的配置来新建一个EventBus对象。 #EventBuspublic static EventBusBuilder builder() {return new EventBusBuilder();}#EventBusBuilder/** Builds an EventBus based on the current configuration. */public EventBus build() {return new EventBus(this);}然后通过下面的调用来设置 EventBus.builder().eventInheritance(false).logSubscriberExceptions(false).build().register(this);拿到EventBus对象以后我们可以调用其register方法进行订阅者注册了。 public void register(Object subscriber) {Class? subscriberClass subscriber.getClass();ListSubscriberMethod subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}首先获取订阅者类subscriber然后通过findSubscriberMethods方法获取该类中以Subscribe注解的函数由于一个类中可能监听多个事件因此获取的方法可能是多个所有的方法赋值到一个List列表中然后遍历这个列表进行注册。 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {Class? eventType subscriberMethod.eventType;Subscription newSubscription new Subscription(subscriber, subscriberMethod);CopyOnWriteArrayListSubscription subscriptions subscriptionsByEventType.get(eventType);if (subscriptions null) {subscriptions new CopyOnWriteArrayList();subscriptionsByEventType.put(eventType, subscriptions);} else {if (subscriptions.contains(newSubscription)) {throw new EventBusException(Subscriber subscriber.getClass() already registered to event eventType);}}int size subscriptions.size();for (int i 0; i size; i) {if (i size || subscriberMethod.priority subscriptions.get(i).subscriberMethod.priority) {subscriptions.add(i, newSubscription);break;}}ListClass? subscribedEvents typesBySubscriber.get(subscriber);if (subscribedEvents null) {subscribedEvents new ArrayList();typesBySubscriber.put(subscriber, subscribedEvents);}subscribedEvents.add(eventType);….}上面就是注册最主要的代码步骤解析如下 根据注解方法获取监听事件的类型eventType并对订阅者subscriber和订阅函数subscriberMethod建立一个订阅关系对象newSubscription 根据eventType在subscriptionsByEventTypeHashMap中获取所有该事件类型的订阅关系列表subscriptions 如果订阅关系列表subscriptions为空就新建一个然后以key为eventTypevalue为newSubscription添加进去 如果订阅关系列表subscriptions不为空判断是否存在newSubscription如果存在说明之前已经注册过抛出异常 如果订阅关系列表subscriptions不为空列表页没有订阅关系newSubscription我们遍历添加进去这里通过订阅函数的priority 来决定存放在列表中的位置从这里也能看出priority 越大存放位置越靠前和上一篇中分析的值越大优先级越高越优先接收到事件。我们可以猜出是通过遍历这个表来进行事件发送的在表里的位置越靠前越先收到事件。 然后通过订阅者subscriber在另一个HashMap - typesBySubscriber中获取该订阅者订阅的所有事件因为一个订阅者可以订阅多个不同的事件因此获取的是个List列表subscribedEvents 首先判断subscribedEvents列表是不是空的如果是空说明以前没有订阅过任何事件新建一个List然后以key为subscribervalue为subscribedEvents添加到typesBySubscriber 然后在新建的subscribedEvents中添加我们订阅的事件eventType。 这里出现了两个HashMapsubscriptionsByEventType与typesBySubscriber通过上面的解析可以知道 subscriptionsByEventType一个事件可能有多个订阅者key是事件value是所有订阅该事件的所有的订阅者 typesBySubscriber一个订阅者可能订阅多个事件key是订阅者value是订阅者订阅的所有事件 看命名就知道By后面的是key值前面的是value值一个好的命名就是这样吧。 解注册源码逻辑 在使用EventBus时注册完后我习惯接着去写解注册的代码怕后面会忘因此按照写代码习惯在讲下解注册的源码实现。 /** Unregisters the given subscriber from all event classes. */public synchronized void unregister(Object subscriber) {ListClass? subscribedTypes typesBySubscriber.get(subscriber);if (subscribedTypes ! null) {for (Class? eventType : subscribedTypes) {unsubscribeByEventType(subscriber, eventType);}typesBySubscriber.remove(subscriber);} else {logger.log(Level.WARNING, Subscriber to unregister was not registered before: subscriber.getClass());}}如果是我们自己写这部分代码根据前面注册的过程我们肯定是要把添加到两个HashMap中的值移除掉。好了看上面源码首先在typesBySubscriber中获取该订阅者订阅的事件列表subscribedTypes 如果为空说明该订阅者没有订阅任何事件无任何操作如果不为空遍历所有事件调用unsubscribeByEventType方法进行解注册然后在typesBySubscriber中移除这个订阅者subscriber。 /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */private void unsubscribeByEventType(Object subscriber, Class? eventType) {ListSubscription subscriptions subscriptionsByEventType.get(eventType);if (subscriptions ! null) {int size subscriptions.size();for (int i 0; i size; i) {Subscription subscription subscriptions.get(i);if (subscription.subscriber subscriber) {subscription.active false;subscriptions.remove(i);i–;size–;}}}}在上一个方法中已经把typesBySubscriber这个订阅者移除了那么unsubscribeByEventType函数就是遍历事件所有的订阅者然后把解注册的订阅者在subscriptionsByEventType中给移除掉。上面的逻辑就是干这个事情。不过一边遍历一边移除是有风险的这个大家要注意index需要也跟着进行减少。 总结下注册和解注册就是往两个HashMap添加和移除数据的过程。 事件发送post源码逻辑 /** Posts the given event to the event bus. */public void post(Object event) {PostingThreadState postingState currentPostingThreadState.get();ListObject eventQueue postingState.eventQueue;eventQueue.add(event);····}上面是部分post代码第一行先解释这个变量currentPostingThreadState及内部类PostingThreadState。 private final ThreadLocalPostingThreadState currentPostingThreadState new ThreadLocalPostingThreadState() {Overrideprotected PostingThreadState initialValue() {return new PostingThreadState();}};/** For ThreadLocal, much faster to set (and get multiple values). */final static class PostingThreadState {final ListObject eventQueue new ArrayList();boolean isPosting;boolean isMainThread;Subscription subscription;Object event;boolean canceled;}currentPostingThreadState是一个ThreadLocal相当于是线程的私有财产里面维护的变量只属于当前线程线程间不会共享。维护的变量是一个自定义类PostingThreadState用来保存发送线程的发送状态信息当前线程是否为主线程是否在发送事件发送的事件列表、接收事件的订阅者等。 /** Posts the given event to the event bus. */public void post(Object event) {PostingThreadState postingState currentPostingThreadState.get();ListObject eventQueue postingState.eventQueue;eventQueue.add(event);if (!postingState.isPosting) {postingState.isMainThread isMainThread();postingState.isPosting true;if (postingState.canceled) {throw new EventBusException(Internal error. Abort state was not reset);}try {while (!eventQueue.isEmpty()) {postSingleEvent(eventQueue.remove(0), postingState);}} finally {postingState.isPosting false;postingState.isMainThread false;}}}现在继续看post逻辑。首先获取到当前线程的发送状态postingState然后拿到事件列表并把需要post的事件加入到列表中。判断是否启动了事件发送流程如果已经启动了不在做处理加入列表中的事件会轮到处理。如果没有启动就启动处理流程并将isPosting赋值为true。循环从事件列表中获取事件通过postSingleEvent进行处理。 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {Class? eventClass event.getClass();boolean subscriptionFound false;if (eventInheritance) {ListClass? eventTypes lookupAllEventTypes(eventClass);int countTypes eventTypes.size();for (int h 0; h countTypes; h) {Class? clazz eventTypes.get(h);subscriptionFound | postSingleEventForEventType(event, postingState, clazz);}} else {subscriptionFound postSingleEventForEventType(event, postingState, eventClass);}if (!subscriptionFound) {if (logNoSubscriberMessages) {logger.log(Level.FINE, No subscribers registered for event eventClass);}if (sendNoSubscriberEvent eventClass ! NoSubscriberEvent.class eventClass ! SubscriberExceptionEvent.class) {post(new NoSubscriberEvent(this, event));}}}在postSingleEvent中有一个变量的判断eventInheritance这个变量表示是否查找发送事件的父类或接口的订阅者默认是true。例如发送事件MsgEvent这个对象MsgEvent继承至Event这个抽象类发送后不光所有订阅MsgEvent的订阅者可以收到事件所有订阅Event的这个事件的订阅者也会收到事件。前面有分析这个字段的值是可以重新配置的代码如下。 EventBus.builder().eventInheritance(false) //发送的时候不考虑事件父类.logSubscriberExceptions(false).build().register(this);eventInheritance为true通过lookupAllEventTypes向上找到所有父类事件类然后遍历找到所有事件的订阅者并发送事件如果为false直接将当前事件发送给订阅者。 postSingleEvent函数主要是找到需要post的所有相关事件然后进一步调用postSingleEventForEventType发送给订阅者因此函数后面的逻辑是判断postSingleEventForEventType的返回值subscriptionFound即判断当前事件有没有订阅者进行处理如果没有处理的会发送一个NoSubscriberEvent。例如如果我在上一节的例子中post一个新的对象student但是没有订阅者和接收函数如果监听了NoSubscriberEvent会收到一个NoSubscriberEvent的事件告知调用者你post的对象没有订阅者。 Subscribe() public void onMsgEventReceived(NoSubscriberEvent event) {Log.i(TAG, NoSubscriberEvent : event); }Student student new Student(1,jane); EventBus.getDefault().post(student);private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class? eventClass) {CopyOnWriteArrayListSubscription subscriptions;synchronized (this) {subscriptions subscriptionsByEventType.get(eventClass);}if (subscriptions ! null !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event event;postingState.subscription subscription;boolean aborted;try {postToSubscription(subscription, event, postingState.isMainThread);aborted postingState.canceled;} finally {postingState.event null;postingState.subscription null;postingState.canceled false;}if (aborted) {break;}}return true;}return false;}从前面分析可知最后都走到了postSingleEventForEventType这个函数里面首先在subscriptionsByEventType中找到所有订阅该事件的订阅者subscriptionssubscriptions为空或者个数是0则返回false。有订阅者的话遍历订阅者然后通过postToSubscription进行发送并返回true。 private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {switch (subscription.subscriberMethod.threadMode) {case POSTING:invokeSubscriber(subscription, event);break;case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster ! null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(subscription, event);}break;case BACKGROUND:if (isMainThread) {backgroundPoster.enqueue(subscription, event);} else {invokeSubscriber(subscription, event);}break;case ASYNC:asyncPoster.enqueue(subscription, event);break;default:throw new IllegalStateException(Unknown thread mode: subscription.subscriberMethod.threadMode);}}这段代码比较简单就是根据订阅者中注解Subscribe中threadMode值来分别进行处理上一节也讲过POSTING表示在哪个线程发送就在哪个线程接收处理因此直接调用invokeSubscriber通过反射来调用订阅者中的接收事件的方法。 void invokeSubscriber(Subscription subscription, Object event) {try {subscription.subscriberMethod.method.invoke(subscription.subscriber, event);} catch (InvocationTargetException e) {handleSubscriberException(subscription, event, e.getCause());} catch (IllegalAccessException e) {throw new IllegalStateException(Unexpected exception, e);}}如果threadMode是MAIN而当前线程是子线程通过 mainThreadPoster.enqueue(subscription, event)将事件加入主线程队列。 mainThreadSupport builder.getMainThreadSupport(); mainThreadPoster mainThreadSupport ! null ? mainThreadSupport.createPoster(this) : null;public interface MainThreadSupport {boolean isMainThread();Poster createPoster(EventBus eventBus); }public class DefaultAndroidMainThreadSupport implements MainThreadSupport {public boolean isMainThread() {return Looper.getMainLooper() Looper.myLooper();}Overridepublic Poster createPoster(EventBus eventBus) {return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);} }mainThreadPoster是由mainThreadSupport 创建的mainThreadSupport是MainThreadSupport实例而MainThreadSupport是一个接口实现类为DefaultAndroidMainThreadSupport因此最终是调用到的DefaultAndroidMainThreadSupport中的createPoster新建了一个HandlerPoster。 public class HandlerPoster extends Handler implements Poster {private final PendingPostQueue queue;private final int maxMillisInsideHandleMessage;private final EventBus eventBus;private boolean handlerActive;public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {super(looper);this.eventBus eventBus;this.maxMillisInsideHandleMessage maxMillisInsideHandleMessage;queue new PendingPostQueue();}public void enqueue(Subscription subscription, Object event) {PendingPost pendingPost PendingPost.obtainPendingPost(subscription, event);synchronized (this) {queue.enqueue(pendingPost);if (!handlerActive) {handlerActive true;if (!sendMessage(obtainMessage())) {throw new EventBusException(Could not send handler message);}}}}Overridepublic void handleMessage(Message msg) {…} }从上面的源码可以看到HandlerPoster就是一个Handler当执行mainThreadPoster.enqueue(subscription, event)时会将订阅者和事件封装成一个PendingPost然后加入到PendingPostQueue这个队列中如果handlerActive为true表示当前Handler正常处理事件将入队列的事件等着被处理即可。如果为false则启动处理调用sendMessage发送消息。 public class HandlerPoster extends Handler implements Poster {private final PendingPostQueue queue;private final int maxMillisInsideHandleMessage;private final EventBus eventBus;private boolean handlerActive;public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {super(looper);…}public void enqueue(Subscription subscription, Object event) {…}Overridepublic void handleMessage(Message msg) {boolean rescheduled false;try {long started SystemClock.uptimeMillis();while (true) {PendingPost pendingPost queue.poll();if (pendingPost null) {synchronized (this) {// Check again, this time in synchronizedpendingPost queue.poll();if (pendingPost null) {handlerActive false;return;}}}eventBus.invokeSubscriber(pendingPost);long timeInMethod SystemClock.uptimeMillis() - started;if (timeInMethod maxMillisInsideHandleMessage) {if (!sendMessage(obtainMessage())) {throw new EventBusException(Could not send handler message);}rescheduled true;return;}}} finally {handlerActive rescheduled;}} }在handleMessage()方法将中将PendingPost对象循环出队列交给invokeSubscriber()方法进一步处理。这样就把线程通过Handler切回了主线程。 backgroundPoster.enqueue()和asyncPoster.enqueue也类似内部都是先将事件入队列然后再出队列但是会通过线程池去进一步处理事件。 粘性事件发送postSticky源码逻辑 public void postSticky(Object event) {synchronized (stickyEvents) {stickyEvents.put(event.getClass(), event);}// Should be posted after it is putted, in case the subscriber wants to remove immediatelypost(event);}从上面代码可以看到先把事件放在了stickyEvents列中中然后调用了post也就是上面我们解析过的流程。让我们再来回顾下注册的代码 // Must be called in synchronized blockprivate void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {Class? eventType subscriberMethod.eventType;Subscription newSubscription new Subscription(subscriber, subscriberMethod);CopyOnWriteArrayListSubscription subscriptions subscriptionsByEventType.get(eventType);…subscribedEvents.add(eventType);if (subscriberMethod.sticky) {if (eventInheritance) {// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class - ListClass).SetMap.EntryClass?, Object entries stickyEvents.entrySet();for (Map.EntryClass?, Object entry : entries) {Class? candidateEventType entry.getKey();if (eventType.isAssignableFrom(candidateEventType)) {Object stickyEvent entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}} else {Object stickyEvent stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}}注册源码分析的时候就分析到subscriberMethod.sticky这个句上面现在让我们看看下面的逻辑同样先判断eventInheritance的值然后将之前放在stickyEvents中的事件拿出来执行checkPostStickyEventToSubscription。 private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {if (stickyEvent ! null) {// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)// – Strange corner case, which we dont take care of here.postToSubscription(newSubscription, stickyEvent, isMainThread());}}checkPostStickyEventToSubscription中的代码比较水又调用了postToSubscription这个方法上面贴出来了这里方面看再贴一遍熟悉的味道 private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {switch (subscription.subscriberMethod.threadMode) {case POSTING:invokeSubscriber(subscription, event);break;case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster ! null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(subscription, event);}break;case BACKGROUND:if (isMainThread) {backgroundPoster.enqueue(subscription, event);} else {invokeSubscriber(subscription, event);}break;case ASYNC:asyncPoster.enqueue(subscription, event);break;default:throw new IllegalStateException(Unknown thread mode: subscription.subscriberMethod.threadMode);}}所以在注册的时候如果你订阅者的接收方法加了sticky注解那么在注册的时候就会看下订阅的事件之前有没有通过postSticky发送过如果有就会立马收到这个事件。 以上是我们平时使用过程的源码解析码字不易喜欢就点赞收藏啊。 参考文章 EventBus 原理解析