继续记录面试题
坐在工位,没事干心慌的不行,可能也是房贷压的。一闲下来就开始胡思乱想,无法沉下心去背那些八股文。这才刚刚接到离职通知第三天啊。而且、我还在坐班呢!!! 哎、怪不得有句老话说的,人穷志短,别人都说解放了 可以休息几天了。我是心焦、心慌、不停的刷BOSS; 所以还是找点事情干,不然待压抑死。看到boss广场上有人发面试题,咱也就当自己去面试了,看看怎么回答。
目录
面试官:能给我说说关于RecycleView的LayoutManager相关的吗?
面试官:线程池中的线程如果销毁
面试官:view绘制流程简述下
面试官:简述Binder原理
面试官:ActivityThread AMS WMS的工作原理
面试官:ContentProvider是如何实现数据共享的
面试官:能给我说说关于RecycleView的LayoutManager相关的吗?
首先、LayoutManager是RecycleView的一个重要组件,负责子项布局和视图回收。决定RecycleView的排列方式,内置了 线性、横向、瀑布流等布局。特殊布局可以自定义LayoutManager;并且它还提供操作列表的相关api,比如获取屏幕上可见的item位置,快速滚动等。
如果延伸,就是陈述下如何自定义LayoutManager。
自定义LayoutManager必须关注其核心方法 onLayoutChildren ; 这个方法是继承LayoutManger必须实现的方法。它负责所有子Item的布局,也就是决定显示那些Item,如果排列回收。一般都是数据变化时被调用。其次是 generateDefaultLayoutParams ; 返回默认布局参数,必须实现;其次就是是否可滑动、横向、竖向等方法。
import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerViewclass CustomLayoutManager : RecyclerView.LayoutManager() {// 必须实现,提供默认布局参数override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {return RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)}// 是否支持纵向滚动override fun canScrollVertically(): Boolean = true// 用于追踪滑动偏移private var verticalScrollOffset = 0// 核心布局方法override fun onLayoutChildren(recycler: RecyclerView.Recycler,state: RecyclerView.State) {// 没有item直接返回if (itemCount == 0) {detachAndScrapAttachedViews(recycler)return}// 回收所有子ViewdetachAndScrapAttachedViews(recycler)var offsetY = verticalScrollOffsetvar topOffset = -offsetY// 布局每一个itemfor (i in 0 until itemCount) {val view = recycler.getViewForPosition(i)addView(view)measureChildWithMargins(view, 0, 0)val width = getDecoratedMeasuredWidth(view)val height = getDecoratedMeasuredHeight(view)layoutDecorated(view, 0, topOffset, width, topOffset + height)topOffset += height// 超出下边界不再布局if (topOffset > height + height) break}}// 纵向滑动处理override fun scrollVerticallyBy(dy: Int,recycler: RecyclerView.Recycler,state: RecyclerView.State): Int {val travel = dy// 更新偏移量verticalScrollOffset += travel// 限制滑动范围if (verticalScrollOffset < 0) {verticalScrollOffset = 0}// 最大滑动到最后一个item底部val maxScroll = getTotalHeight() - heightif (verticalScrollOffset > maxScroll) {verticalScrollOffset = maxScroll}// 移动所有子ViewoffsetChildrenVertical(-travel)onLayoutChildren(recycler, state)return travel}// 计算所有item的总高度private fun getTotalHeight(): Int {var totalHeight = 0for (i in 0 until itemCount) {totalHeight += 100 // 这里假设每个item高度为100,可根据实际测量}return totalHeight}
}
上面是一个简单的自定义LayoutManager 帮助大家理解。回答的话上面的话能说出来,基本算是过关了。
面试官:线程池中的线程如果销毁
线程池中的线程由线程池统一管理,非核心线程空闲超过keepAliveTime会被自动销毁,关闭线程时,所有线程会被完全销毁,无需手动。销毁线程池 shutdown 方法会等待提交任务,销毁所有线程。shutdownNow方法会尝试立即终止所有线程。
面试官:lock和syncrognized原理区别,适合什么场景。
synchronized 是JVM层面的内置锁、适合简单互斥场景。Lock是显示锁,功能更丰富,支持超时、中断、公平锁等,适合复杂的并发场景。
面试官:view绘制流程简述下
View的绘制流程分为measure layout draw三个阶段,分别是确定view的尺寸,位置、显示内容。由ViewRootImpi递归完成整个view绘制。
其中measure 阶段是 View 绘制流程的第一步,主要负责测量每个 View 的宽高。它通过 MeasureSpec 约束进行递归测量,最终每个 View 都会保存自己的尺寸,为后续 layout 和 draw 阶段做准备;
面试官:简述Binder原理
Binder是android的核心IPC机制,通过内核Binder驱动和序列化技术,实现不同进程间通讯,
追问:怎么Binder怎么做到一次copy的?
- Binder 通过共享内存(mmap)机制实现一次拷贝:
- Client 进程和 Server 进程都通过 Binder 驱动映射一块缓冲区到各自用户空间。
- 客户端写数据到缓冲区,驱动只需把缓冲区引用传递给服务端。
- 服务端直接从映射区读取数据,无需再做一次拷贝。
- 数据流:Client 用户空间 → Binder 映射区(内核空间) → Server 用户空间(同一块物理内存)
- 这样只需一次物理内存拷贝,大大提升了 IPC 性能。
面试官:ActivityThread AMS WMS的工作原理
ActivityThread 是应用进程的主线程管理类,负责组件创建和消息分发。AMS 运行在 system_server,负责 Activity 和进程的调度与生命周期管理。WMS 管理所有窗口的显示、层级和输入事件。三者通过 Binder 通信,协作实现应用的启动、界面显示和系统调度
面试官:ContentProvider是如何实现数据共享的
ContentProvider 提供了统一的访问接口(CRUD:query、insert、update、delete),其他应用可通过标准 URI 访问其数据
首次面试归来,微信视频面试。紧张、还有就是对于自己的认知;真的是不学习新技术就要落后。现在主流是kotlin,而我真正的kotlin项目是 18年。这就比较尴尬,对于现在kotlin的新特性,高阶函数一问三不知。另外,对于自己的语言表达能力表示唾弃~ 真的太久不和人交流,语言组织能力就会退化。
面试官问:讲下你现在的项目框架搭建。
我当前项目是一个地图类应用,采用了组件化架构和MVVM模式;项目组件化架构分为Library,和module ,其中library是公共组件部分,比如网络库组件、数据库组件、widget 通用组件,base组件等。而Module是对业务的拆分,如首页、组队、算路、导航等。每个组件独立开发,维护。我在团队中负责 框架搭建、Library库开发维护;
其实目前框架的技术选型有点问题,我们是地图类项目,要求整个项目共用一个主图,那么就只能采用单Activity+NFragment,但是有使用了组件化架构导致Fragment的退出栈都需要自己去管理,并且地图的管理也需要抽出管理类。
面试官:那你们是怎么管理的?
我们采用多个单利去管理比如FragmentController、MapController ,这些管理类堆积在Base组件内,满足每个业务组件的调用。我们把对于Fragment、或这地图的操作都由这两个管理去控制,模块自身不允许直接操控 map。