From adf2cd1008839897290e6048462e565678dd5a1b Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Mon, 3 Aug 2020 09:51:28 +0800 Subject: [PATCH] Update --- blogs/Android/口水话/View 体系相关口水话.md | 50 ++++++++++++++++++- .../口水话/四大组件的启动流程口水话.md | 5 +- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/blogs/Android/口水话/View 体系相关口水话.md b/blogs/Android/口水话/View 体系相关口水话.md index c5ee4f3..fcbb204 100644 --- a/blogs/Android/口水话/View 体系相关口水话.md +++ b/blogs/Android/口水话/View 体系相关口水话.md @@ -7,6 +7,7 @@ View 体系相关口水话 1. View 绘制流程 2. View 事件分发 3. View 刷新机制 +4. 项目总结 #### View 绘制流程 @@ -76,4 +77,51 @@ IMS 在 Native 层创建了两个线程,InputReaderThread 和 InputDispatcherT Choreographer 主要是用来接收 Vsync 信号,并且在信号到来时去处理一些回调事件。事件类型有四种,分别是 Input、Animation、Traversal、Commit。在 Vsync 信号到来时,会依次处理这些事件,前三种比较好理解,第四种 Commit 是用来执行组件的 onTrimMemory 函数的。Choreographer 是通过 FrameDisplayEventReceiver 来监听底层发出的 Vsync 信号的,然后在它的回调函数 onVsync 中去处理,首先会计算掉帧,然后就是 doCallbacks 处理上面所说的回调事件。 -Vsync 信号可以理解为底层硬件的一个消息脉冲,它每 16ms 发出一次,它有两种方式发出,一种是 HWComposer 硬件产生,一种是用软件模拟,即 VsyncThread。不管使用哪种方式,都统一由 DispSyncThread 进行分发。 \ No newline at end of file +Vsync 信号可以理解为底层硬件的一个消息脉冲,它每 16ms 发出一次,它有两种方式发出,一种是 HWComposer 硬件产生,一种是用软件模拟,即 VsyncThread。不管使用哪种方式,都统一由 DispSyncThread 进行分发。 + +#### 项目总结 + +##### 自定义 View + +待定。 + +##### 事件分发 + +熟悉事件分发是处理嵌套滑动的基础。 + +在项目中,我们遇到了一个 ViewPager2 嵌套 RecyclerView 滑动过于灵敏的问题,即稍微滑动一点 RecyclerView 就会导致 ViewPager2 切换,这在使用 ViewPager 是没啥问题,但是 ViewPager2 内部使用的也是 RecyclerView + SnapHelper 做横向滑动,导致了滑动灵敏问题。又因为 ViewPager2 是 final 的,所以只能使用内部拦截法。 + +解决办法是:重写 ViewPager2 的根布局 FrameLayout 的 dispatchTouchEvent,判断如果 dx>dy+30,即表明是横向滑动,requestDisallowTouchEvent(false) 允许 ViewPager2 去拦截处理。详细代码如下: + +```java + int dx = 0; + int dy = 0; + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + dx = (int) ev.getRawX(); + dy = (int) ev.getRawY(); + getParent().requestDisallowInterceptTouchEvent(false); + break; + case MotionEvent.ACTION_MOVE: + if (Math.abs(dx - ev.getRawX()) > Math.abs(dy - ev.getRawY()) + 80) { + getParent().requestDisallowInterceptTouchEvent(false); + } else { + getParent().requestDisallowInterceptTouchEvent(true); + } + break; + case MotionEvent.ACTION_UP: + dx = 0; + dy = 0; + getParent().requestDisallowInterceptTouchEvent(false); + break; + default: + break; + } + return super.dispatchTouchEvent(ev); + } +``` + diff --git a/blogs/Android/口水话/四大组件的启动流程口水话.md b/blogs/Android/口水话/四大组件的启动流程口水话.md index 83f48ce..79af082 100644 --- a/blogs/Android/口水话/四大组件的启动流程口水话.md +++ b/blogs/Android/口水话/四大组件的启动流程口水话.md @@ -45,4 +45,7 @@ bindService 的流程要比 startService 流程复杂很多,不过核心就是 在 ContextImpl 的 bindService 中,会首先把 ServiceConnection 通过 getServiceDispatcher 调用转化成一个 IServiceConnection 接口,这个 IServiceConnection 是一个 Binder 对象,所以就可以跨进程传递给 Activity 了。然后就是获取 AMS 的代理对象,去执行 bindService 调用。这个方法会传入 AppplicationThread、ActivityToken 以及 Intent。在 AMS 成功将 Service 组件启动起来之后,就会把这个 Binder 对象封装成一个消息,发送给 Activity 组件所运行的应用程序的主线程消息队列中,最后在分发给 Activity 组件内部的成员变量 ServiceConnection 的 onServiceConnected 来处理。Activity 组件获得了 Service 组件的访问接口之后,就可以调用其相关服务了。 -至此,绑定服务的流程就讲完了,虽然省略了很多,但是大致流程还是很清楚地嘛~ \ No newline at end of file +至此,绑定服务的流程就讲完了,虽然省略了很多,但是大致流程还是很清楚地嘛~ + +#### BroadcastReceiver 的启动流程 +