副标题[/!--empirenews.page--]
背景
对于Android开发,在面试的时候,经常会被问到,说一说View的绘制流程?我也经常问面试者,View的绘制流程.
对于3年以上的开发人员来说,就知道onMeasure/onLayout/onDraw基本,知道他们呢是干些什么的,这样就够了吗?
如果你来我们公司,我是你的面试官,可能我会考察你这三年都干了什么,对于View你都知道些什么,会问一些更细节的问题,比如LinearLayout的onMeasure,onLayout过程?他们都是什么时候被发起的,执行顺序是什么?
如果以上问题你都知道,可能你进来我们公司就差不多了(如果需要内推,可以联系我,Android/IOS 岗位都需要),可能我会考察你draw的 canvas是哪里来的,他是怎么被创建显示到屏幕上呢?看看你的深度有多少?
对于现在的移动开发市场逐渐趋向成熟,趋向饱和,很多不缺人的公司,都需要高级程序员.在说大家也都知道,面试要造飞机大炮,进去后拧螺丝,对于一个3年或者5年以上Android开发不稍微了解一些Android深一点的东西,不是很好混.扯了这么多没用的东西,还是回到今天正题,Android的绘图原理浅析.
本文介绍思路
从面试题中几个比较容易问的问题,逐层深入,直至屏幕的绘图原理.
在讲Android的绘图原理前,先介绍一下Android中View的基本工作原理,本文暂不介绍事件的传递流程。
View 绘制工作原理
我们先理解几个重要的类,也是在面试中经常问到的
Activity,Window(PhoneWindow),DecorView之间的关系
理解他们三者的关系,我们直接看代码吧,先从Activity开始的setContentView开始(注:代码删除了一些不是本次分析流程的代码,以免篇幅过长)
- //Activity
- /**
- * Set the activity content from a layout resource. The resource will be
- * inflated, adding all top-level views to the activity.
- *
- * @param layoutResID Resource ID to be inflated.
- *
- * @see #setContentView(android.view.View)
- * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
- */
- public void setContentView(@LayoutRes int layoutResID) {
- getWindow().setContentView(layoutResID);
- initWindowDecorActionBar();
- }
-
- public Window getWindow() {
- return mWindow;
- }
里面调用的getWindow的setContentView,这个接下来讲,那么这个mWindow是何时被创建的呢?
- //Activity
- private Window mWindow;
- final void attach(Context context, ActivityThread aThread,····) {
- attachBaseContext(context);
- mFragments.attachHost(null /*parent*/);
- mWindow = new PhoneWindow(this, window, activityConfigCallback);
- }
在Activity的attach中创建了PhoneWindow,PhoneWindow是Window的实现类.
继续刚才的setContentView
- //PhoneWindow
- @Override
- public void setContentView(int layoutResID) {
- if (mContentParent == null) {
- installDecor();
- } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
- mContentParent.removeAllViews();
- }
- if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
- final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
- getContext());
- transitionTo(newScene);
- } else {
- mLayoutInflater.inflate(layoutResID, mContentParent);
- }
- }
在setContentView中,如果mContentParent为空,会去调用installDecor,最后将布局infalte到mContentParent.在来看一下installDecor
- //PhoneWindow
- // This is the view in which the window contents are placed. It is either
- // mDecor itself, or a child of mDecor where the contents go.
- ViewGroup mContentParent;
-
- private DecorView mDecor;
-
- private void installDecor() {
- mForceDecorInstall = false;
- if (mDecor == null) {
- mDecor = generateDecor(-1);
- } else {
- mDecor.setWindow(this);
- }
- if (mContentParent == null) {
- mContentParent = generateLayout(mDecor);
- }
- }
- protected DecorView generateDecor(int featureId) {
- return new DecorView(context, featureId, this, getAttributes());
- }
在installDecor,创建了一个DecorView.看mContentParent的注释我们可以知道,他本身就是mDecor或者是mDecor的contents部分.
(编辑:520站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|