本文详细介绍了Android中的Surface系统,采用情景分析的办法,详解了何为SurfaceFlinger,以及SurfaceFlinger的工作流程,以Activity函数调用为切入点来研究SurfaceFlinger。

一 目的

深入浅出 详解Android Surface系统(Android surface)  SurfaceFlinger Surface Activity Android 第1张

本篇文章的目的就是为了讲清楚Android中的Surface系统,大家耳熟能详的SurfaceFlinger到底是个什么东西,它的工作流程又是怎样的。当然,鉴于SurfaceFlinger的复杂性,我们依然将采用情景分析的办法,找到合适的切入点。

一个Activity是怎么在屏幕上显示出来的呢?我将首先把这个说清楚。

接着我们把其中的关键调用抽象在Native层,以这些函数调用为切入点来研究SurfaceFlinger。好了,开始我们的征途吧。

二 Activity是如何显示的

最初的想法就是,Activity获得一块显存,然后在上面绘图,最后交给设备去显示。这个道理是没错,但是Android的SurfaceFlinger是在System Server进程中创建的,Activity一般另有线程,这之间是如何...如何挂上关系的呢?我可以先提前告诉大家,这个过程还比较复杂。

好吧,我们从Activity最初的启动开始。代码在framework/base/core/java/Android/app/ActivityThread.java中,这里有个函数叫handleLaunchActivity。

[---->ActivityThread:: handleLaunchActivity()]

  1. privatefinalvoidhandleLaunchActivity(ActivityRecordr,IntentcustomIntent){
  2. Activitya=performLaunchActivity(r,customIntent);
  3. if(a!=null){
  4. r.createdConfig=newConfiguration(mConfiguration);
  5. BundleoldState=r.state;
  6. handleResumeActivity(r.token,false,r.isForward);
  7. ---->调用handleResumeActivity
  8. }

handleLaunchActivity中会调用handleResumeActivity。

[--->ActivityThread:: handleResumeActivity]

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }

上面addView那几行非常关键,它关系到咱们在Activity中setContentView后,整个Window到底都包含了些什么。我先告诉大家。所有你创建的View之上,还有一个DecorView,这是一个FrameLayout,另外还有一个PhoneWindow。上面这些东西的代码在framework/Policies/Base/Phone/com/android/Internal/policy/impl。这些隐藏的View的创建都是由你在Acitivty的onCreate中调用setContentView导致的。

[---->PhoneWindow:: addContentView]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }

installDecor将创建mDecor和mContentParent。mDecor是DecorView类型,ContentParent是ViewGroup类型

  1. privatevoidinstallDecor(){
  2. if(mDecor==null){
  3. mDecor=generateDecor();
  4. mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
  5. mDecor.setIsRootNamespace(true);
  6. }
  7. if(mContentParent==null){
  8. mContentParent=generateLayout(mDecor);

那么,ViewManager wm = a.getWindowManager()又返回什么呢?

PhoneWindow从Window中派生,Acitivity创建的时候会调用它的setWindowManager。而这个函数由Window类实现。

代码在framework/base/core/java/android/view/Window.java中:

  1. publicvoidsetWindowManager(WindowManagerwm,IBinderappToken,StringappName){
  2. mAppToken=appToken;
  3. mAppName=appName;
  4. if(wm==null){
  5. wm=WindowManagerImpl.getDefault();
  6. }
  7. mWindowManager=newLocalWindowManager(wm);
  8. }

你看见没,分析JAVA代码这个东西真的很复杂。mWindowManager的实现是LocalWindowManager,但由通过Bridge模式把功能交给WindowManagerImpl去实现了。

真的很复杂!

好了,我们回到wm.addView(decor, l)。最终会由WindowManagerImpl来完成addView操作,我们直接看它的实现好了。

代码在framework/base/core/java/android/view/WindowManagerImpl.java:

[---->addView]

  1. privatevoidaddView(Viewview,ViewGroup.LayoutParamsparams,booleannest)
  2. {
  3. ViewRootroot;//ViewRoot,我们的主人公终于登场!
  4. synchronized(this){
  5. root=newViewRoot(view.getContext());
  6. root.mAddNesting=1;
  7. view.setLayoutParams(wparams);
  8. if(mViews==null){
  9. index=1;
  10. mViews=newView[1];
  11. mRoots=newViewRoot[1];
  12. mParams=newWindowManager.LayoutParams[1];
  13. }else{
  14. }
  15. index--;
  16. mViews[index]=view;
  17. mRoots[index]=root;
  18. mParams[index]=wparams;
  19. }
  20. root.setView(view,wparams,panelParentView);
  21. }

ViewRoot是整个显示系统中最为关键的东西,看起来这个东西好像和View有那么点关系,其实它根本和View等UI关系不大,它不过是一个Handler罢了,唯一有关系的就是它其中有一个变量为Surface类型。我们看看它的定义。ViewRoot代码在framework/base/core/java/android/view/ViewRoot.java中:

  1. publicfinalclassViewRootextendsHandlerimplementsViewParent,
  2. View.AttachInfo.Callbacks
  3. {
  4. privatefinalSurfacemSurface=newSurface();
  5. }

它竟然从handler派生,而ViewParent不过定义了一些接口函数罢了。

看到Surface直觉上感到它和SurfaceFlinger有点关系。要不先去看看?

Surface代码在framework/base/core/java/android/view/Surface.java中,我们调用的是无参构造函数。

  1. publicSurface(){
  2. mCanvas=newCompatibleCanvas();//就是创建一个Canvas!
  3. }

如果你有兴趣的话,看看Surface其他构造函数,最终都会调用native的实现,而这些native的实现将和SurfaceFlinger建立关系,但我们这里ViewRoot中的mSurface显然还没有到这一步。那它到底是怎么和SurfaceFlinger搞上的呢?这一切待会就会水落石出的。

另外,为什么ViewRoot是主人公呢?因为ViewRoot建立了客户端和SystemServer的关系。我们看看它的构造函数。

  1. publicViewRoot(Contextcontext){
  2. super();
  3. ....
  4. getWindowSession(context.getMainLooper());
  5. }

getWindowsession将建立和WindowManagerService的关系。

  1. publicstaticIWindowSessiongetWindowSession(LoopermainLooper){
  2. synchronized(mStaticInit){
  3. if(!mInitialized){
  4. try{
  5. //sWindowSession是通过Binder机制创建的。终于让我们看到点希望了
  6. InputMethodManagerimm=InputMethodManager.getInstance(mainLooper);
  7. sWindowSession=IWindowManager.Stub.asInterface(
  8. ServiceManager.getService("window"))
  9. .openSession(imm.getClient(),imm.getInputContext());
  10. mInitialized=true;
  11. }catch(RemoteExceptione){
  12. }
  13. }
  14. returnsWindowSession;
  15. }
  16. }

上面跨Binder的进程调用另一端是WindowManagerService,代码在framework/base/services/java/com/android/server/WindowManagerService.java中。我们先不说这个。

回过头来看看ViewRoot接下来的调用。

[-->ViewRoot::setView()],这个函数很复杂,我们看其中关键几句。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
0

requestLayout实现很简单,就是往handler中发送了一个消息。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
1

我们看看跨进程的那个调用。sWindowSession.add。它的最终实现在WindowManagerService中。

[--->WindowSession::add()]

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
2

WindowSession是个内部类,会调用外部类的addWindow。

这个函数巨复杂无比,但是我们的核心目标是找到创建显示相关的部分。所以,最后精简的话就简单了。

[--->WindowManagerService:: addWindow]

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
3

WindowState类中有一个和Surface相关的成员变量,叫SurfaceSession。它会在attach函数中被创建。SurfaceSession嘛,就和SurfaceFlinger有关系了。我们待会看。

好,我们知道ViewRoot创建及调用add后,我们客户端的View系统就和WindowManagerService建立了牢不可破的关系。

另外,我们知道ViewRoot是一个handler,而且刚才我们调用了requestLayout,所以接下来消息循环下一个将调用的就是ViewRoot的handleMessage。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
4

performTraversals更加复杂无比,经过我仔细挑选,目标锁定为下面几个函数。当然,后面我们还会回到performTraversals,不过我们现在更感兴趣的是Surface是如何创建的。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
5

[---->ViewRoot:: relayoutWindow()]

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
6

我们赶紧转到WindowManagerService去看看吧。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
7

[--->WindowState::createSurfaceLocked]

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
8

这里使用了Surface的另外一个构造函数。

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,booleanisForward){
  2. booleanwillBeVisible=!a.mStartedActivity;
  3. if(r.window==null&&!a.mFinished&&willBeVisible){
  4. r.window=r.activity.getWindow();
  5. Viewdecor=r.window.getDecorView();
  6. decor.setVisibility(View.INVISIBLE);
  7. ViewManagerwm=a.getWindowManager();
  8. WindowManager.LayoutParamsl=r.window.getAttributes();
  9. a.mDecor=decor;
  10. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  11. if(a.mVisibleFromClient){
  12. a.mWindowAdded=true;
  13. wm.addView(decor,l);//这个很关键。
  14. }
9

到这里,不进入JNI是不可能说清楚了。不过我们要先回顾下之前的关键步骤。

◆ add中,new了一个SurfaceSession

◆创建new了一个Surface

◆调用copyFrom,把本地Surface信息传到outSurface中#p#

JNI层

上面两个类的JNI实现都在framework/base/core/jni/android_view_Surface.cpp中。

[---->SurfaceSession:: SurfaceSession()]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
0

它的init函数对应为:

[--->SurfaceSession_init]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
1

Surface的init对应为:

[--->Surface_init]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
2

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
3

[--->Surface_copyFrom]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
4

这里仅仅是SurfaceControl的转移,但是并没有看到Surface相关的信息。

那么Surface在哪里创建的呢?为了解释这个问题,我使用了终极武器,aidl。

1 终极武器AIDL

aidl可以把XXX.aidl文件转换成对应的java文件。我们刚才调用的是WindowSession的

relayOut函数。如下:

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
5

它的aidl文件在framework/base/core/java/android/view/IWindowSession.aidl中

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
6

刚才说了,JNI及其JAVA调用只是copyFrom了SurfaceControl对象到outSurface中,但是没看到哪里创建Surface。这其中的奥秘就在aidl文件编译后生成的java文件中。

你在命令行下可以输入:

aidl -Id:\android-2.2-froyo-20100625-source\source\frameworks\base\core\java\ -Id:\android-2.2-froyo-20100625-source\source\frameworks\base\Graphics\java d:\android-2.2-froyo-20100625-source\source\frameworks\base\core\java\android\view\IWindowSession.aidl test.java

以生成test.java文件。-I参数指定include目录,例如aidl有些参数是在别的java文件中指定的,那么这个-I就需要把这些目录包含进来。

先看看ViewRoot这个客户端生成的代码是什么。

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
7

真奇怪啊,Binder客户端这头竟然没有把outSurface的信息发过去。我们赶紧看看服务端。

服务端这边处理是在onTranscat函数中。

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
8

太诡异了!竟然有这么多花花肠子。我相信如果没有aidl的帮助,我无论如何也不会知道这其中的奥妙。

那好,我们的流程明白了。

◆客户端虽然传了一个surface,但其实没传递给服务端

◆服务端调用writeToParcel,把信息写到Parcel中,然后数据传回客户端

◆客户端调用Surface的readFromParcel,获得surface信息。

那就去看看writeToParcel吧。

[---->Surface_writeToParcel]

  1. publicvoidaddContentView(Viewview,ViewGroup.LayoutParamsparams){
  2. if(mContentParent==null){//刚创建的时候mContentParent为空
  3. installDecor();
  4. }
  5. mContentParent.addView(view,params);
  6. finalCallbackcb=getCallback();
  7. if(cb!=null){
  8. cb.onContentChanged();
  9. }
  10. }
9

那看看客户端的Surface_readFromParcel吧。

[----->Surface_readFromParcel]

  1. privatevoidinstallDecor(){
  2. if(mDecor==null){
  3. mDecor=generateDecor();
  4. mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
  5. mDecor.setIsRootNamespace(true);
  6. }
  7. if(mContentParent==null){
  8. mContentParent=generateLayout(mDecor);
0

到此,我们终于七拐八绕的得到了surface,这其中经历太多曲折了。下一节,我们将精简这其中复杂的操作,统一归到Native层,以这样为切入点来了解Surface的工作流程和原理。

好,反正你知道ViewRoot调用了relayout后,Surface就真正从WindowManagerService那得到了。继续回到ViewRoot,其中还有一个重要地方是我们知道却不了解的。

  1. privatevoidinstallDecor(){
  2. if(mDecor==null){
  3. mDecor=generateDecor();
  4. mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
  5. mDecor.setIsRootNamespace(true);
  6. }
  7. if(mContentParent==null){
  8. mContentParent=generateLayout(mDecor);
1

[--->ViewRoot::draw()]

  1. privatevoidinstallDecor(){
  2. if(mDecor==null){
  3. mDecor=generateDecor();
  4. mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
  5. mDecor.setIsRootNamespace(true);
  6. }
  7. if(mContentParent==null){
  8. mContentParent=generateLayout(mDecor);
2

看起来,这个surface的用法很简单嘛:

l lockSurface,得到一个画布Canvas

l 调用View的draw,让他们在这个Canvas上尽情绘图才。另外,这个View会调用所有它的子View来画图,最终会进入到View的onDraw函数中,在这里我们可以做定制化的界面美化工作。当然,如果你想定制化整个系统画图的话,完全可以把performTranvsal看懂,然后再修改。

l unlockCanvasAndPost,告诉Surface释放这块画布

当然,这几个重要函数调用干了具体的活。这些重要函数,我们最终会精简到Native层的。

2 总结

到这里,你应该知道了一个Activity中,调用setContentView后它如何从系统中获取一块Surface,以及它是如何使用这个Surface的了。不得不说,关于UI这块,Android绝对是够复杂的。难怪2.3把UI这块代码基本重写一遍,希望能够简单精炼点。

【编辑推荐】

  1. Android开发:自定义GridView/ListView数据源
  2. Android自定义标题栏:显示网页加载进度
  3. Android应用开发教程:两个运行的Activity之间的通信
  4. Android学习笔记:Activity跳转

转载请说明出处
知优网 » 深入浅出 详解Android Surface系统(Android surface)

发表评论

您需要后才能发表评论