1.Activityçåºç¡ç¥è¯(ä¸)
2.从源码方面来分析Fragment管理中 Add() 方法
3.Android Activity Deeplink启动来源获取源码分析
4.Android-Fragment源码分析
5.❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
6.Android源码阅读分析:ActivityManagerService分析(一)——启动流程
Activityçåºç¡ç¥è¯(ä¸)
ä¸ç¯æ»ç»äºActivityçä¸äºç¥è¯,源码ç°å¨ç»§ç»å¯¹Activityçç¥è¯è¿è¡æ¢³ç,å æ¬Activityç´æ¥ä¼ éæ°æ®,Activityççå½å¨æ,Activityçå¯å¨æ¨¡å¼ç.
1.intentä¼ éæ°æ®:
使ç¨startActivityæ¹æ³,intentçputExtra()æ¹æ³,以é®å¼å¯¹çå½¢å¼ä¼ éæ°æ®,该æ¹æ³æå¾å¤éè½½æ¹æ³,å¯ä»¥æ ¹æ®ä¼ éæ°æ®çä¸åç±»åéæ©åéçæ¹æ³.é¤äºæputExtra()æ¹æ³å¤,è¿æputExtras()æ¹æ³,ä¼ éçåæ°æ¯Bundle.
å¦æä¼ éçæ¯å¯¹è±¡,è¿ä¸ªå¯¹è±¡è¦å®ç°åºåå,ä¹å°±æ¯å®ç°Parcelableæè Serializableæ¥å£.
å¦æå¸æ被å¯å¨ç页é¢è¿åæ°æ®,éè¦ä½¿ç¨startActivityForResult()æ¹æ³,è¿ä¸ªæ¹æ³ä¸éè¦è®¾ç½®è®¿é®å·,ç¨æ¥åºåä¸åç访é®è .并ä¸å¨å¯å¨é¡µéåonActivityResultæ¹æ³ç¨æ¥æ¥æ¶è¿åçæ°æ®,
2.两ç§æ åµä¸çActivityççå½å¨æ.
æ£å¸¸æ åµä¸ççå½å¨æ,æ£å¸¸æ åµæ¯æç¨æ·çæ£å¸¸æä½ä¸çActivityççå½å¨æ.åé¢ä¼åæå¼å¸¸æ åµä¸ççå½å¨æ.
onCreate: Activity第ä¸æ¬¡å建æ¶åçåè°,主è¦æ¯å¨è¿ä¸ªæ¹æ³è¿è¡åå§åå·¥ä½,æ¯å¦åå§åæ§ä»¶åäºä»¶ç»å®å·¥ä½.
onStart:Activityä»ä¸å¯è§ç¶æåæå¯è§ç¶æ.
onResume:Activityåæåå°,å¯ä»¥åç¨æ·äº¤äº.
onPause:Activityå¯è§ä½æ¯ä¸è½åç¨æ·äº¤äº.
onStop:Activityä»å¯è§åå¾ä¸å¯è§,æ为åå°Activity.
onDestroy:Activityéæ¯æ¶è°ç¨.
onRestart:Activityä»åå°åæåå°Activity.
å¨å¯å¨Activityå两个Activityä¹é´è·³è½¬æ¶,å¯ä»¥ç¥éActivityççå½å¨æååè¿ç¨,æ两个说æ:(1)å¨ä¸¤ä¸ªActivity跳转æ¶,第ä¸ä¸ªActivtyçonPause,onStopæ¹æ³å第äºä¸ªActivityççå½å¨ææ¹æ³è°ç¨æ¶æº.
第ä¸ä¸ªActivityå æ§è¡onPauseæ¹æ³,第äºä¸ªActivityæè½å建.è¿ä¹å°±æå³çå¨onPauseæ¹æ³ä¸ä¸è½æ§è¡å¤ªèæ¶çæä½,å¦åä¼å½±å第äºä¸ªActivityçå建.å¨æºç (ActivityStack)ä¸æè¿æ ·ç注é:
(2)onStartåonResume,onPauseåonStopè¿ä¸¤å¯¹æ¹æ³çå®è´¨ä¸åå¤:onStartåonStopè¿ä¸¤ä¸ªæ¹æ³æ¯ä»Activityçå¯è§æ§æ¥åºåç,onResumeåonPauseæ¯ä»Activityæ¯å¦å¤äºåå°,æ¯å¦å¯ä»¥åç¨æ·äº¤äºæ¥åºåç,注æå¨onPauseè°ç¨æ¶Activityè¿æ¯å¯è§ç,è°ç¨æ¶æºæ¯å¦å¼¹åºdialogæ¶,ä¸é¢çActivityæ¯å¯è§ç.è¿ä¸ªæ¶åè°ç¨çæ¯onPauseæ¹æ³.
å¼å¸¸æ åµä¸Activityççå½å¨æ:å¼å¸¸æ åµä¸æ¯æèµæºç¸å ³é ç½®åçååæåå°Activity被系ç»åæ¶æ¶Activityççå½å¨æ.åå°Activity被系ç»åæ¶çæ åµæ¯è¾é¾å¤ç°,å¨èµæºç¸å ³é ç½®åçååæ¶ååå°Activity被åæ¶æ¶ççå½å¨ææ§è¡è¿ç¨æ¯ä¸æ ·ç,æ¯è¾å®¹æå¤ç°çå°±æ¯æ¨ªç«å±åæ¢æ¶ççå½å¨ææ§è¡è¿ç¨.å¨ AndroidManifestçActivityç»ä»¶ä¸é ç½®android:screenOrientationæ ç¾,å½è®¾ç½®å¯ä»¥æ¨ªç«æ¹åéçæ¹åæåºå¨æ¥è°èæ¶,å¨åæ¢æ¶ä¼åºç°å éæ¯Activityåå建çè¿ç¨.
è¿ç¨:
å¨è¿ç§æ åµä¸æå¯è½ä¼ææ°æ®ç丢失,ç³»ç»æä¾ç¨æ¥ä¿åæ°æ®åè¿åæ°æ®çæ¹æ³:onSaveInstanceStateåonRestoreInstanceState.ç¨æ¹æ³åæ°Bundleå¯ä»¥ä¿ååè¿åæ°æ®.
å¯ä»¥æ ¹æ®éè¦è®¾ç½®android:screenOrientationæ ç¾,设å®activityçæ¹å,å¦æactivityçæ¹åæ¯éè¦æ¨ªç«å±åæ¢,ä½æ¯ä¸å®¹è®¸éæ¯Activity,å¯ä»¥è®¾ç½®å¦ä¸æ ç¾,å½è¿äºæ åµ(常ç¨ç)åçååæ¯ä¸ä¼éæ°èµ°Activityççå½å¨ææ¹æ³,åªä¼è°ç¨onConfigurationChanged,å¯ä»¥æ ¹æ®æ åµå¨è¿ä¸ªæ¹æ³éæ´æ°æä½.
åæ¢æ¶çlogè¾åº
3.Activityçåç§å¯å¨æ¨¡å¼
æ å:æ¯Activityçé»è®¤å¯å¨æ¨¡å¼,对äºAndroidManifestçActivityèç¹ä¸çandroid:launchMode="standard"æ ç¾.
ç¹å®:æ¯æ¬¡å¯å¨é½ä¼éæ°å建æ°çActivity.
singleTop:对åºçAndroidManifesçActivityèç¹ä¸çandroid:launchMode="singleTop"æ ç¾
ç¹ç¹:å½æ¤æ¨¡å¼çActivityå¤äºæ 顶æ¶,ä¸ä¼éæ°å建æ°çActivity,ä¼è°ç¨onNewIntentæ¹æ³,å¦ææ´æ°Activityçintent,éè¦è°ç¨ setIntent()æ¹æ³,å ·ä½ççå½å¨æè¿ç¨
singleTask:å¨activityæ ä¸å·²ç»æéè¦åå¯å¨çactivityæ¶,ä¼å æ¸ é¤ä½äºéè¦å¯å¨activityä¹ä¸çactivity,ä¾å¦:å¯å¨é¡ºåºmainActivity-activityA -activityB-activityA,å ¶ä¸activityAæ¯singleTaskçå¯å¨æ¨¡å¼:
singleInstance:å¨ä¸ä¸ªæ ä¸åç¬åå¨çactivity.
å ³äºactivityæ :æ¯æç¨æ¥ç®¡çactivityä¸ç§"å è¿å åº"çéåç»æ,æ¥çactivity对åºæ çæ¹æ³:ActivityçgetTaskId()æ¹æ³,åä¸ä¸ªæ çidå¼æ¯ç¸åç.adb shell dumpsys activityå¨ç»ç«¯æ¥çæ ç»æ,æ¯å¦è¿æ¯ä¸é¢çactivityå¯å¨é¡ºåº,ä¸åæ¯ActivityAè¿æ¯è®¾ç½®æsingleInstance,è¿æ¯çæ ç»æ:æ两个TaskRecord,å ¶ä¸ActivityBåMainActivityä½äºåä¸ä¸ªæ ä¸.
4.Activityå¼åä¸ä½¿ç¨æå·§:
<1>å®ä¹ä¸ä¸ªç¶Activity,å¨å建æ°çActivityæ¶ç»§æ¿è¿ä¸ªactivityå³å¯,å°ä¸äºactivityçå ¬å ±è®¾ç½®å¯ä»¥è®¾ç½®å¨ç¶activityä¸,æ¯å¦è·åæ¯ä¸ªActivityçåå,设置activityççªä½å±æ§,åä¸ç®¡çactivityççå½å¨æç,
<2>å¨å¯å¨çactivityä¸å®ä¹éææ¹æ³,å¯å¨æ¡ä»¶ä¼æ¾èæè§:
<3>管çactivityç±»,ç¨æ¥ä¸é®éåºapp.å¨ç¶ç±»Activityçå建åéæ¯æ¶ç¨æ¥æ·»å å移é¤Activity,å¨éè¦ä¸é®éåºçå°æ¹è°ç¨éæfinishAllActivityæ¹æ³.
从源码方面来分析Fragment管理中 Add() 方法
本文深入解析了Android中Fragment管理中的关键方法——Add()。Add()方法作为添加Fragment的解析基础操作,其用法直观且简便。源码例如,解析向Activity中添加一个Fragment的源码代码如下:
getSupportFragmentManager().beginTransaction().add(R.id.fragmenta,new FragmentA()).commit();
在实际应用中,我们通常需要添加多个Fragment以实现界面的解析非常准的k线买卖点源码动态切换。如微信底部导航栏,源码每个按钮对应一个不同的解析Fragment。通过Add()方法配合hide和show,源码可以实现Fragment之间的解析平滑切换。
我们以两个Fragment为例,源码实现了MainActivity的解析布局和内容。通过简单的源码代码实现,我们观察到Fragment的解析生命周期。初次运行时,源码输出如下日志;点击FragmentB后,再次点击FragmentA和B时,日志显示FragmentA和B只会初始化一次,证明了通过hide和show进行切换时,初始化效果的实现。
接着,我们介绍了replace方法。replace方法实际上包含了remove和add的组合,用于在FragmentManager中替换Fragment。若切换到下一个Fragment时,上一个Fragment不再需要,可以使用replace方法。若需要保留上一个Fragment,API提供了相应的addBackToStack方法。
修改MainActivity代码中的逻辑,再次执行并观察日志。在初次初始化时,spark 源码编译安装日志保持一致;点击FragmentB后,发现Fragment调用了destroy方法,而点击FragmentA时,界面显示的仍是FragmentB。此时,我们修改了逻辑,使得每次切换时,Fragment都会重新调用onCreateView到onDestroyView的所有方法,实现了布局层的完整销毁和重建。
特别提醒,当进行Fragment嵌套时,若需要在返回时跳过中间的Fragment,使用FragmentManager.popBackStackImmediate方法可以实现弹出指定TAG的Fragment,并清除其之前的Fragment,从而实现更深层次的返回。
本文代码示例和完整代码资源可以通过点击此处传送门获取,或者查看下方小卡片。
最后,我想强调的是,技术的追求永无止境。对于程序员而言,不断提升自己,对每一行代码、每一个工具负责,深入理解其底层原理,是提升技术能力的关键。Android架构师之路漫长而艰辛,与君共勉。
Android Activity Deeplink启动来源获取源码分析
Deeplink在业务模块中作为外部应用的入口提供,不同跳转类型可能会导致应用提供不一致的服务,通常通过反射调用Activity中的jq源码查看其mReferrer字段获取跳转来源的包名。然而,mReferrer存在被伪造的风险,可能导致业务逻辑出错或经济损失。因此,我们需要深入分析mReferrer的来源,并寻找更为安全的获取方法。
为了深入了解mReferrer的来源,我们首先使用搜索功能在Activity类中查找mReferrer,发现其在Attach方法中进行赋值。进一步通过断点调试跟踪调用栈,发现Attach方法是由ActivityThread.performLaunchActivity调用的。而performLaunchActivity在调用Attach时,传入的referrer参数实际上是一个ActivityClientRecord对象的referrer属性。深入分析后,发现referrer是在ActivityClientRecord的构造函数中被赋值的。通过进一步的调试发现,ActivityClientRecord的实例化来自于LaunchActivityItem的mReferrer属性。接着,我们分析了mReferrer的来源,发现它最终是由ActivityStarter的setCallingPackage方法注入的。而这个setCallingPackage方法的调用者是ActivityTaskManagerService的startActivity方法,进一步追踪调用链路,我们发现其源头是在App进程中的ActivityTaskManager.getService()方法调用。
在分析了远程服务Binder调用的过程后,我们发现获取IActivityTaskManager.Stub的方法是ActivityTaskManager.getService()。这使得我们能够追踪到startActivity方法的调用,进而找到发起Deeplink的应用调用的具体位置。通过这个过程,我们确定了mReferrer实际上是通过Activity的getBasePackageName()方法获取的。
为了防止包名被伪造,我们注意到ActivityRecord中还包含PID和Uid。html源码上传sae通过使用Uid结合包管理器的方法来获取对应的包名,可以避免包名被伪造。通过验证Uid的来源,我们发现Uid实际上是通过Binder.getCallingUid方法获取的,且Binder进程是无法被应用层干涉的,因此Uid是相对安全的。接下来,我们可以通过Uid来置换包名,进一步提高安全性。
总结,mReferrer容易被伪造,应谨慎使用。通过使用Uid来获取包名,可以提供一种更为安全的获取方式。此过程涉及对源代码的深入分析和调试,作者Chen Long为vivo互联网客户端团队成员。
Android-Fragment源码分析
Fragment是Android系统为了提高应用性能和降低资源消耗而引入的一种更轻量级的组件,它允许开发者在同一个Activity中加载多个UI组件,实现页面的切换与回退。Fragment可以看作是Activity的一个子部分,它有自己的生命周期和内容视图。
在实际应用中,Fragment可以用于构建动态、可复用的UI组件,例如聊天应用中,左右两边的布局(联系人列表和聊天框)可以分别通过Fragment来实现,通过动态地更换Fragment,达到页面的切换效果,而无需整个页面的刷新或重新加载。
在实现上,v4.Fragment与app.Fragment主要区别在于兼容性。房产带采集源码app.Fragment主要面向Android 3.0及以上版本,而v4.Fragment(即支持包Fragment)则旨在提供向下兼容性,支持Android 1.6及更高版本。使用v4.Fragment时,需要继承FragmentActivity并使用getSupportFragmentManager()方法获取FragmentManager对象。尽管从API层面看,两者差异不大,但官方倾向于推荐使用v4.Fragment,以确保更好的兼容性和性能优化。
下面的示例展示了如何使用v4.Fragment实现页面的加载与切换。通过创建Fragment和FragmentActivity,我们可以加载特定的Fragment,并在不同Fragment间进行切换。
在FragmentDemo的布局文件中,定义了Fragment容器。
在Fragment代码中,定义了具体的业务逻辑和视图渲染,如初始化界面数据、响应用户事件等。
在Activity代码中,通过FragmentManager的beginTransaction方法,加载指定的Fragment实例,并在需要时切换到不同Fragment,实现页面的动态更新。
从官方的建议来看,v4.Fragment已经成为推荐的使用方式,因为它在兼容性、性能和功能方面都更优于app.Fragment。随着Android系统的迭代,使用v4.Fragment能确保应用在不同版本的Android设备上均能获得良好的运行效果。
在Fragment的生命周期管理中,Fragment与Activity的生命周期紧密关联。通过FragmentManager的操作,如commit、replace等,可以将Fragment加入到Activity的堆栈中,实现页面的加载与切换。当用户需要返回时,系统会自动将当前Fragment从堆栈中移除,从而实现页面的回退。
深入Fragment源码分析,我们可以了解其如何在底层实现这些功能。Fragment的初始化、加载、切换等过程涉及到多个关键类和方法,如FragmentManager、FragmentTransaction、BackStackRecord等。通过这些组件的协作,Fragment能够实现与Activity的生命周期同步,确保用户界面的流畅性和高效性。
在实际开发中,使用Fragment可以显著提高应用的响应速度和用户体验。通过动态加载和切换不同的Fragment,开发者可以构建出更加灵活、高效的应用架构,同时减少资源的消耗,提高应用的性能。
❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
Android系统中,Window、Activity、View之间的关系是紧密相连且相互作用的。了解这三者之间的关系,有助于深入理解Android应用的渲染和交互机制。
在Android中,通常在创建Activity时会调用`setContentView()`方法,以指定显示的布局资源。这个方法主要作用是将指定的布局添加到一个名为`DecorView`的容器中,并最终将其显示在屏幕上。这一过程涉及到多个组件的交互,下面分步骤解析。
在`Activity`类中,`setContentView()`方法调用`getWindow()`方法获取`Window`对象,而`Window`对象在`Activity`的`attach()`方法中被初始化。`Window`对象是一个抽象类,其默认实现为`PhoneWindow`,这是Android特定的窗口实现。
`PhoneWindow`在创建时会通过`setWindowManager()`方法与`WindowManager`进行关联。`WindowManager`是系统级组件,用于管理所有的窗口,包括窗口的创建、更新、删除等操作。`WindowManager`的管理最终由`WindowManagerService`(WMS)执行,这是一个运行在系统进程中的服务。
在`PhoneWindow`中,`installDecor()`方法会初始化`DecorView`和`mContentParent`。`mContentParent`是一个`ViewGroup`,用于存放`setContentView()`传入的布局。通过`mLayoutInflater`的`inflate()`方法,将指定的布局资源添加到`mContentParent`中。
`DecorView`是一个特殊的`FrameLayout`,包含了`mContentParent`。在完成布局的添加后,`DecorView`本身并没有直接与`Activity`建立联系,也没有被绘制到屏幕上显示。`DecorView`的绘制和显示发生在`Activity`的`onResume()`方法执行后,这时`Activity`中的内容才真正可见。
当`Activity`执行到`onCreate()`阶段时,其内容实际上并没有显示在屏幕上,直到执行到`onResume()`阶段,`Activity`的内容才被真正显示。这一过程涉及到`ActivityThread`中的`handleResumeActivity()`方法,该方法会调用`WindowManager`的`addView()`方法,将`DecorView`添加到`WindowManagerService`中,完成`DecorView`的绘制和显示。
`WindowManagerService`通过`addView()`方法将`DecorView`添加到显示队列中,并且在添加过程中,会创建关键的`ViewRootImpl`对象,进一步管理`DecorView`的布局、测量和绘制。`ViewRootImpl`会调用`mWindowSession`的`addToDisplay()`方法,将`DecorView`添加到真正的显示队列中。
`mWindowSession`是`WindowManagerGlobal`中的单例对象,其内部实际上是一个`IWindowSession`类型,通过`AIDL`接口与系统进程中的`Session`对象进行通信,最终实现`DecorView`的添加和显示。
通过`setView()`方法的实现,可以看到除了调用`IWindowSession`进行跨进程添加`View`之外,还会设置输入事件处理。当触屏事件发生时,这些事件首先通过驱动层的优化计算,通过`Socket`跨进程通知`Android Framework`层,最终触屏事件会通过输入管道传送到`DecorView`处理。
在`DecorView`内部,触屏事件会通过`onProcess`方法传递给`mView`,即`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源码阅读分析:ActivityManagerService分析(一)——启动流程
本文深入解析了Android源码中的ActivityManagerService,即AMS的核心功能与启动流程。AMS作为管理Android四大组件的关键组件,其重要性不言而喻。本篇将从AMS的创建与启动逻辑开始分析,为理解其内部机制打下基础。
AMS的创建始于SystemServer的startBootstrapServices方法。此方法通过SystemServiceManager的startService方法启动Lifecycle类实例,从而创建AMS对象。Lifecycle作为适配器,连接了AMS与SystemService之间的交互。再通过Lifecycle的构造器,创建出AMS实例。
创建过程中,AMS线程、UI线程、CpuTracker线程和系统目录被初始化,同时StackSupervisor与ActivityStarter也得以创建,完成AMS对象的创建。
随后,ActivityManagerService的startService(SystemService)方法执行,完成服务的注册与启动。Lifecycle的onStart方法调用ActivityManagerService的start方法,启动关键操作。
在SystemServer的startBootstrapServices方法中,创建完AMS后,执行其setSystemProcess方法,为系统进程启动Application实例与服务注册。然后,SystemServer继续调用startBootstrapServices、startCoreServices与startOtherServices方法,启动更多系统服务与持久化进程,完成桌面Activity的启动与广播发布。
文中总结了AMS创建与启动的关键步骤,并预告后续文章将深入探讨AMS的具体使用、对四大组件的管理以及内存管理等内容。通过本篇解析,读者能更直观地理解Android系统中AMS的核心功能与作用。