Android

作者: minehdcxy | 来源:发表于2021-09-19 14:20 被阅读0次

一、 Parcelable 和 Serializable 区别

  1. Parcelable是Android的接口,Serializable是java接口,都用于实现对象的序列化和反序列化
  2. Serializable的序列化和反序列化过程需要I/O操作,将对象转换为二进制流,方便在网络、内存中传输和将对象持久化到本地, Serializable的反序列化过程需要通过反射的模式创建对象,会产生大量的临时变量,如果需要序列化的对象很多的话有可能会频繁的触发GC导致系统触发stop the word, 从而导致系统卡顿。频繁的I/O操作也会影响性能。
  3. Parcelable是基于内存实现的序列化和反序列化,写入过程会按照顺序写入内存,读取的时候需要把指针复位然后根据指针size按照顺序读取,所以要求写入顺序和读取顺序一致,因为没有I/O操作所以会更快。同时Parcelable也支持将序列化之后的数据存入到磁盘,但是也需要I/O;
    二 、Android 冷启动流程


    截屏2021-09-20 下午8.34.58.png
  4. Launcher 启动Activity
  5. 获取AMS代理对象启动Activity
  6. 构建ActivityStarter 执行execute
  7. 构建ActivityStack
  8. 判断如果进程不存在则重新创建通知AMS创建进程
  9. 进程为空创建进程执行ActivityThread main()
  10. 创建主线程Looper,并调用attach方法给AMS绑定客户端回调,用来控制Activity的整个启动流程
  11. ApplicationThread 回调handleCreateActivity,创建Activity对象,并执行attach方法,同时创建Window、WindowManager,并且将两者绑定
  12. setContentView 构建DectorView 和 parentContent, 并且将LayoutId解析完成后添加到parentContent
  13. ApplicationThread 回调handleResumeActivity,调用WindowManager addView(),添加DectorView
  14. GlobalWindowManager 调用addView(),添加DectorView
  15. 创建ViewRootImpl对象,并且调用setView(),添加DectorView,
  16. 执行ViewRootImpl#requestLayout, 向主线程MessageQueue发送同步屏障,并且发送消息
  17. 执行WindowManagerService.addToDisplayUser(),将ViewRootImpl的aidl接口和WindowManagerService绑定
  18. 垂直同步信号回调之后执行DectorView的绘制动作,执行measure layout draw 方法
    总结:ViewRoomImpl 是系统服务和所有子view的桥接

三、同步屏障

  1. 如何添加同步屏障到MessageQueue
 private int postSyncBarrier(long when) {
        // Enqueue a new sync barrier token.
        // We don't need to wake the queue because the purpose of a barrier is to stall it.
        synchronized (this) {
            final int token = mNextBarrierToken++;
            final Message msg = Message.obtain();
            msg.markInUse();
            msg.when = when;
            msg.arg1 = token;
            //注意这里,同步屏障消息的msg的target字段为空

            Message prev = null;
            //p为对头
            Message p = mMessages;
            if (when != 0) {
                //找到同步屏障消息的when的合适插入节点
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
            }
            //插入同步屏障消息
            if (prev != null) { // invariant: p == prev.next
                msg.next = p;
                prev.next = msg;
            } else {
                msg.next = p;
                mMessages = msg;
            }
            return token;
        }
    }

按照这样的插入方法,当前的同步屏障消息只能过滤后面消息,在看一下MesssageQueue的next()方法。

  1. 同步屏障如何过滤同步消息
 Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            //还未到下一个任务的执行时间,线程休眠
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //判断消息是否是同步屏障消息,如果是的话,找到下一个*异步*消息
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                //执行将消息从队列里取出来的动作,前驱指针和后继指针相互配合将消息从队列里取出来
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
                //.....
    }
  1. 如何删除同步屏障删除的
public void removeSyncBarrier(int token) {
        // Remove a sync barrier token from the queue.
        // If the queue is no longer stalled by a barrier then wake it.
        synchronized (this) {
            Message prev = null;
            Message p = mMessages;
            //找同步屏障节点
            while (p != null && (p.target != null || p.arg1 != token)) {
                prev = p;
                p = p.next;
            }
            if (p == null) {
                throw new IllegalStateException("The specified message queue synchronization "
                        + " barrier token has not been posted or has already been removed.");
            }
            final boolean needWake;
            if (prev != null) {
                //找到了删除节点
                prev.next = p.next;
                needWake = false;
            } else {
                //一个都没找到
                mMessages = p.next;
                needWake = mMessages == null || mMessages.target != null;
            }
            p.recycleUnchecked();

            // If the loop is quitting then it is already awake.
            // We can assume mPtr != 0 when mQuitting is false.
            if (needWake && !mQuitting) {
                //唤醒线程,将队列激活
                nativeWake(mPtr);
            }
        }
    }
  1. 总结,同步屏障的作用是为了更优先的执行MessageQueue里的异步消息,比如ViewRootImpl里在绘制之前发出的同步屏障消息

四、 Choreographer

  1. Choreographer用户申请VSync(垂直同步信号),并在下一个Sync到来的时候回调,然后执行队列里的输入、动画等绘制逻辑。
  2. Choreographer是线程单例的和Looper一样。
  3. Choreographer中的关键对象有FrameDisplayEventReceiver(用来申请VSync, 回调VSync信号处理队列中的任务),FrameHandler(用来像当前线程发送消息),CallbackQueue(大小为4数组,每个数组的元素是单链表的头结点,用来记录不同类型的任务)
  4. 如果当前线程的MessageQueue在同步屏障之前还有同步任务在执行,并且执行时间比较长,这样的话就会影响后面的异步任务执行,这个时候如果超出了30真的阈值,则会Log提示。

相关文章

网友评论

      本文标题:Android

      本文链接:https://www.haomeiwen.com/subject/wrzugltx.html