安卓Activity创建界面过程-API源码解析
来源:互联网 发布:cf出现网络异常 编辑:程序博客网 时间:2024/06/03 05:07
我们知道Android 软件每一个界面 都是Activity构成的 那么Activity 是怎么创建一个界面的呢 ?
接下来是看源码时间 过程复杂 耐心观看
setContentView(R.layout.activity_main);这个大家再熟不过了 onCreate中调用这个就可以创建对应布局文件的界面
接下来看API源码 :
activity中:
public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }getWindow()得到的是一个Window对象
public Window getWindow() { return mWindow; }
Window是一个抽象类 不可能创建对象
那么我们找一下它的实现类 (Activity六千行代码 这是真难找啊 )。
在attach方法中:
// attach 方法是Activity通过反射实例化之后调用的第一个方法 ,之后生命周期的方法才会被调用
可以看到调用了PolicyManager的静态方法
看一下这个PolicyManager
咦 SDK看不了 代码中也调用不了 什么鬼
看一下它所在的包名 :
- com.android.internal.policy.PolicyManager
!!!这根本就不在 android.jar 里
这怎么才能找到这个包里的源码呢
用我上一篇博客说的:http://grepcode.com/ 这个源码浏览网站
找到这个PolicyManager 类里的:
public static Window makeNewWindow(Context context) { return sPolicy.makeNewWindow(context); }再看一下 sPolicy 是什么
它是一个接口 被Policy实现 代码用反射构建了一个Policy对象
(看来离Window类的真面目不远了)。。。。
Policy中的makeNewWindow()方法
public Window makeNewWindow(Context context) { return new PhoneWindow(context); }构造了一个PhoneWindow对象 这就是Window的实现类 也就是它调用了setContentView() 方法 方法内部:
判断没ContentParent 是否为null 是:调用installDecor() ,否:移除内部所有View 。
然后通过 mLayoutInflater.inflate()
LayoutInflater也是个抽象类 ,在PhoneWindow的构造方法中通过静态方法from创建的 它由哪个子类继承的还真不知道
接着说installDecor() ,就截取了开头一段
首先初始化了 mDecor ,通过generateDecor方法 ,看一下:
protected DecorView generateDecor() { return new DecorView(getContext(), -1); }然后找这个构造方法 发现 DecorView是PhoneWindow的内部类 并且是 private final 类型
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
public DecorView(Context context, int featureId) { super(context); mFeatureId = featureId;
}
然后通过 generateLayut(mDecor)方法 把这个上面创建好的mDecor作为参数传递
这个方法很长 ,找到有一段:
View in = mLayoutInflater.inflate(layoutResource, null); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mContentRoot = (ViewGroup) in; ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);这里的layoutResource是 int值 对应我们mainfest中设置的theme主题所对应的屏幕布局
可以是R.layout.screen_custom_title;R.layout.screen_action_bar等等
现在我们知道了 DecorView 就是当前屏幕的除状态栏的区域
下面贴上这个图,你就可以看明白了(转自 工匠若水)
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);把contentParent 变成了 ID_ANDROID_CONTENT 对应的ViewGroup ,这是什么东西 ,看下这个 id
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;R.id.content ? 这怎么像是屏幕状态栏下方的内容区域的 id
通过findViewById给contentParent加上这么个 id
好吧 暂时不理解 必须要看一下上面提到的 decor.addView 到底干了什么 ,看一下R.layout.screen_custom_title 这个布局吧
// 文件位置:frameworks\base\core\res\res\layout (frameworks包下)
<!--This is a custom layout for a screen.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:fitsSystemWindows="true"> <!-- Popout bar for action modes --> <ViewStub android:id="@+id/action_mode_bar_stub" android:inflatedId="@+id/action_mode_bar" android:layout="@layout/action_mode_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="?attr/actionBarTheme" /> <FrameLayout android:id="@android:id/title_container" android:layout_width="match_parent" android:layout_height="?android:attr/windowTitleSize" android:transitionName="android:title" style="?android:attr/windowTitleBackgroundStyle"> </FrameLayout> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" /></LinearLayout>
我们知道这个布局是一个屏幕的布局文件:上面的title_container是用来放自定义Title的容器,而下面的 content 就是放置我们设置的布局的容器
再看一下generateLayut的方法:
View in = mLayoutInflater.inflate(layoutResource, null); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mContentRoot = (ViewGroup) in; ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);啊哦 getDecorView
把整个手机界面给了DecorView 感觉要到了见证奇迹的时候了呢!!!
看下findViewById方法的实现 :
public View findViewById(int id) { return getDecorView().findViewById(id); }
getDecorView 显然是当前PhoneWindow中的DecorView对象 ,通过它把id 为 content的部分给了这个contentParent 然后return
记得 PhoneWindow中的setContentView 方法是这么写的
mLayoutInflater.inflate(layoutResID, mContentParent);
把我们为Activity设置的布局(layoutResId)设置给mContentParent(上面return出来的contentParent)
到这里 我们已经把布局给放到DecorView中 接下来安卓系统就可以为我们显示界面了
且在onResume()刚执行之后,界面还是不可见的,只有执行完Activity.makeVisible(),DecorView才对用户可见
最后拿一张别人的Android的窗口管理框架(转自ariesjzj)
1 0
- 安卓Activity创建界面过程-API源码解析
- 源码解析--activity启动过程
- 源码解析:Activity启动过程全解析
- 安卓欢迎界面创建
- 安卓 重复创建界面
- 源码 Activity 的 window 创建过程
- 安卓Activity界面跳转(QQ)
- 安卓API指南之Activity回顾
- 安卓2048源码解析
- 安卓源码解析网址
- Android源码解析之一Activity启动时界面绘制流程
- Retroft2源码解析01-创建过程
- Android源码解析Window系列第(一)篇---Window的基本认识和Activity的Window创建过程
- 安卓Activity生命周期全解析
- 安卓训练-开始-管理 Activity 生命周期-重新创建 Activity
- Activity的启动过程之startActivity源码解析
- Json解析,安卓内置api
- Activtiy完全解析(一、Activity的创建过程)
- STL_算法_逆转(reverse,reverse_copy)
- HTML之表单标签
- 【JS学习笔记】JS基础上:数据类型
- 四种常见的 POST 提交数据方式
- sql where 1=1 规范代码
- 安卓Activity创建界面过程-API源码解析
- 蓝桥杯-入门训练 Fibonacci数列
- dojo.mixin、dojo.extend、dojo.delegate解析
- JDBC编程中,结果集为空的判断方法
- 方案中加关断通讯功能
- STL_算法_旋转(rotate、rotate_copy)
- C中 malloc()分配堆内存实际的大小
- 在自带的uitableviewcell上面加内容注意点
- iOS开发之常用插件