1.❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
2.android 开发中有一句super.onCreate(savedInstanceState)我
3.找到卡顿来源,源码BlockCanary源码精简分析
4.Jetpackå¦ä¹ ä¹----ViewModel
❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
Android系统中,分析Window、源码Activity、分析View之间的源码关系是紧密相连且相互作用的。了解这三者之间的分析confluence的源码关系,有助于深入理解Android应用的源码渲染和交互机制。
在Android中,分析通常在创建Activity时会调用`setContentView()`方法,源码以指定显示的分析布局资源。这个方法主要作用是源码将指定的布局添加到一个名为`DecorView`的容器中,并最终将其显示在屏幕上。分析这一过程涉及到多个组件的源码交互,下面分步骤解析。分析
在`Activity`类中,源码`setContentView()`方法调用`getWindow()`方法获取`Window`对象,而`Window`对象在`Activity`的`attach()`方法中被初始化。`Window`对象是spring 3 企业应用开发实战 源码一个抽象类,其默认实现为`PhoneWindow`,这是Android特定的窗口实现。
`PhoneWindow`在创建时会通过`setWindowManager()`方法与`WindowManager`进行关联。`WindowManager`是系统级组件,用于管理所有的窗口,包括窗口的创建、更新、删除等操作。`WindowManager`的管理最终由`WindowManagerService`(WMS)执行,这是一个运行在系统进程中的服务。
在`PhoneWindow`中,`installDecor()`方法会初始化`DecorView`和`mContentParent`。`mContentParent`是一个`ViewGroup`,用于存放`setContentView()`传入的布局。通过`mLayoutInflater`的`inflate()`方法,将指定的布局资源添加到`mContentParent`中。
`DecorView`是cocos2d-x游戏源码一个特殊的`FrameLayout`,包含了`mContentParent`。在完成布局的添加后,`DecorView`本身并没有直接与`Activity`建立联系,也没有被绘制到屏幕上显示。`DecorView`的绘制和显示发生在`Activity`的`onResume()`方法执行后,这时`Activity`中的内容才真正可见。
当`Activity`执行到`onCreate()`阶段时,其内容实际上并没有显示在屏幕上,直到执行到`onResume()`阶段,`Activity`的内容才被真正显示。这一过程涉及到`ActivityThread`中的`handleResumeActivity()`方法,该方法会调用`WindowManager`的`addView()`方法,将`DecorView`添加到`WindowManagerService`中,完成`DecorView`的绘制和显示。
`WindowManagerService`通过`addView()`方法将`DecorView`添加到显示队列中,并且在添加过程中,会创建关键的unity3d 手机游戏源码`ViewRootImpl`对象,进一步管理`DecorView`的布局、测量和绘制。`ViewRootImpl`会调用`mWindowSession`的`addToDisplay()`方法,将`DecorView`添加到真正的显示队列中。
`mWindowSession`是`WindowManagerGlobal`中的单例对象,其内部实际上是一个`IWindowSession`类型,通过`AIDL`接口与系统进程中的`Session`对象进行通信,最终实现`DecorView`的添加和显示。
通过`setView()`方法的实现,可以看到除了调用`IWindowSession`进行跨进程添加`View`之外,还会设置输入事件处理。当触屏事件发生时,这些事件首先通过驱动层的优化计算,通过`Socket`跨进程通知`Android Framework`层,最终触屏事件会通过输入管道传送到`DecorView`处理。
在`DecorView`内部,触屏事件会通过`onProcess`方法传递给`mView`,android即时通讯的源码即`PhoneWindow`中的`DecorView`。最终,事件传递到`PhoneWindow`中的`View.java`实现的`dispatchPointerEvent()`方法,并调用`Window.Callback`的`dispatchTouchEvent(ev)`方法。对于`Activity`来说,`dispatchTouchEvent()`方法最终还是会调用`PhoneWindow`的`superDispatchTouchEvent()`,然后传递给`DecorView`的`superDispatchTouchEvent()`方法,完成事件的分发和处理。
综上所述,通过`setContentView()`的过程,我们可以清晰地看到`Activity`、`Window`、`View`之间的交互关系。整个过程主要由`PhoneWindow`组件主导,而`Activity`主要负责提供要显示的布局资源,其与屏幕的直接交互则通过`WindowManager`和`WindowManagerService`实现。
android 开发中有一句super.onCreate(savedInstanceState)我
你要是感兴趣你可以去看源码,学习阶段你不用知道为什么,你可以把super.onCreate(savedInstanceState)删除看看会有什么效果。绝B 会报错。 super.xxxxx错误,Activity fragment必须掉用 super
找到卡顿来源,BlockCanary源码精简分析
通过屏幕渲染机制我们了解到,Android的屏幕渲染是通过vsync实现的。软件层将数据计算好后,放入缓冲区,硬件层从缓冲区读取数据绘制到屏幕上,渲染周期是ms,这让我们看到不断变化的画面。如果计算时间超过ms,就会出现卡顿现象,这通常发生在软件层,而不是硬件层。卡顿发生的原因在于软件层的计算时间需要小于ms,而计算的执行地点则在Handler中,具体来说是在UI的Handler中。Android进程间的交互通过Binder实现,线程间通信通过Handler。
软件层在收到硬件层的vsync信号后,会在Java层向UI的Handler中投递一个消息,进行view数据的计算。这涉及到测量、布局和绘制,通常在`ViewRootImpl`的`performTraversals()`函数中实现。因此,view数据计算在UI的Handler中执行,如果有其他操作在此执行且耗时过长,则可能导致卡顿,我们需要找到并优化这些操作。
要找到卡顿的原因,可以通过在消息处理前后记录时间,计算时间差,将这个差值与预设的卡顿阈值比较。如果大于阈值,表示发生了卡顿,此时可以dump主线程堆栈并显示给开发者。实现这一功能的关键在于在Looper中设置日志打印类。通过`Looper.loop()`函数中的日志打印,我们可以插入自定义的Printer,并在消息执行前后计算时间差。另一种方法是在日志中添加前缀和后缀,根据这些标志判断时间点。
BlockCanary是一个用于检测Android应用卡顿的工具,通过源码分析,我们可以了解到它的实现逻辑。要使用BlockCanary,首先需要定义一个继承`BlockCanaryContext`的类,并重写其中的关键方法。在应用的`onCreate()`方法中调用BlockCanary的安装方法即可。当卡顿发生时,BlockCanary会通知开发者,并在日志中显示卡顿信息。
BlockCanary的核心逻辑包括安装、事件监控、堆栈和CPU信息的采集等。在事件发生时,会创建LooperMonitor,同时启动堆栈采样和CPU采样。当消息将要执行时,开始记录开始时间,执行完毕后停止记录,并计算执行时间。如果时间差超过预设阈值,表示发生了卡顿,并通过回调传递卡顿信息给开发者。
堆栈和CPU信息的获取通过`AbstractSampler`类实现,它通过`post`一个`Runnable`来触发采样过程,循环调用`doSample()`函数。StackSampler和CpuSampler分别负责堆栈和CPU信息的采集,核心逻辑包括获取当前线程的堆栈信息和CPU速率,并将其保存。获取堆栈信息时,通过在`StackSampler`类中查找指定时间范围内的堆栈信息;获取CPU信息时,从`CpuSampler`类中解析`/proc/stat`和`/proc/mpid/stat`文件的CPU数据,并保存。
总结而言,BlockCanary通过在消息处理前后记录时间差,检测卡顿情况,并通过堆栈和CPU信息提供详细的卡顿分析,帮助开发者定位和优化性能问题。
Jetpackå¦ä¹ ä¹----ViewModel
å®æ¹å¦ä¹ ææ¡£ViewModelå°±æ¯åå¨é¡µé¢ç¸å ³çæ°æ®ï¼å¹¶å°è¿äºæ°æ®åActivityãFragmentçæçå½å¨æç¸å ³çç»ä»¶ç¸å ³èï¼èµäºæ°æ®çå½å¨æã
ç¹ç¹ï¼
ViewModelççå½å¨æ
å¨viewModel对象å建æ¶å¼å§ï¼ä¸ç´å°ä»æå ³èççé¢æ§å¶å¨éæ¯æ¶æéæ¯ï¼è¿å°±è¯´æäºå³ä½¿åçäºæ¨ªç«å±åæ¢ï¼çé¢ç¸å ³çæ°æ®ä¹æ¯ä¸ç´åå¨å¹¶ä¸ä¸å横ç«å±åæ¢çå½±åã
é常æ们æ¯å¨ActvityçonCreate()æ¹æ³ä¸æ¥å建ViewModel对象ï¼è¯¥ViewModel对象ä¼ä¸ç´å¨å åä¸ï¼ç´å°è¿ä¸ªActivityéæ¯æ¶æéæ¾èµæºã
ä»ä¸é¢ViewModelçå·¥ä½åçå¯ä»¥å¾ç¥ï¼
1ãViewModel ä¸æ¦å建好äºï¼å°±ä¼ä¸ç´ä¿åå°å½åçé¢æ§å¶å¨ï¼Activity ãFragmentçï¼éæ¯æ¶æä¼éæ¾èµæºï¼
2ãä¸åççé¢æ§å¶å¨ï¼ViewModel ç对象æ¶åå¨ä¸åçHashmapä¸çï¼ä»ä»¬ä¹æ¯ä¸åç对象ï¼å±é¨åä¾ï¼
3ãè¦åå°å ¨å±åä¾ViewModel对象ï¼å¯ä»¥å°ViewModelæ¾å°Applicationä¸å»ï¼
æ¥ä¸æ¥ä»æºç è§åº¦æ¥åæä¸ä¸åçï¼
å¨æ建Activityç对象æ¶ï¼å¨å ¶ç¶ç±»ComponentActivity.javaä¸å®ç°äºæ¥å£ViewModelStoreOwnerï¼å¨å ¶å®ç°æ¹æ³ä¸çæViewModelStore对象
å¨çé¢æ§å¶å¨çæé å½æ°ä¸ï¼å°±æ·»å äºå¯¹çå½å¨æçè§å¯è ï¼èå½è§å¯è æ¶å°å½åççé¢æ§å¶å¨ççå½å¨ææ¯Lifecycle.Event.ON_DESTROYæ¶ï¼å°±ä¼å°mViewModelStore对象mapä¸ææä¿åçviewModelæ¸ çæï¼è¿æ ·æ¥è¾¾å°éæ¾èµæºã
è¿éåªå¤çäºON_DESTROYççå½å¨æç¶æï¼é£ä¹ä¹å°±è¯´æäºå¨ViewModel对象å®ä¾å建æååï¼ä¸ç®¡çé¢æ§å¶å¨ï¼å¦Activityï¼ççå½å¨æï¼é¤ON_DESTROYå¤ï¼å¦ä½åçååï¼ViewModelé½ä¸ä¼è¢«æ¸ çæã
ä»è¿éçåºæ¥ViewModel对åºkeyçå¯ä¸æ§
ViewModelå·¥ä½åççæ ¸å¿ææ¯ç¹ï¼
è§å¯è 模å¼ãå·¥ç¨æ¨¡å¼ãåå°ãHashmapæ°æ®ç»æ
ViewModelå¨MVVMæ¶æ模åä¸ï¼ä¸DataBindingç»å使ç¨ï¼ä¼è®©ä½ æèµ·é£çæè§ãåç»ä¼è¿ä¸æ¥å 深使ç¨ãæ¬ç¯ä» 以å¦ä¼ä½¿ç¨ãäºè§£åç为éç¹ã