Android Display Graphics #从Activity看surface的创建(1)

如果图片链接失败,请扫码查看文章详情。

Android Display Graphics系列文章-汇总

系列文章请扫关注公众号!

创建Activity

Activity是Android系统的应用组件,一般情况下,开发者显示的内容是通过Activity展示的。比如 使用Android studio创建一个空activity的demo,示例代码如下

                                                       

这里的onCreate就调用到了Activity的onCreate,创建一个出来。

setContentView()用来绑定视图,将xml或java代码中的设置视图绑定到Activity上来。

Activity的创建呢,可以理解为3给个对象的创建:Window、DecorView、ViewRootImpl。

 Window的创建

当用户从launcher界面点击一个应用时,Zygote收到相应请求后fork出一个子进程,这个子进程就是APP对应的进程。这个APP的入口函数就是ActivityThread的main函数:

一系列的调用流程是:

ActivityThread#main()初始化调用attach()

-->attach() 创建ApplicationThread,并跨进程传递给AMS管理

-->AMS通过ApplicationThread通知ActivityThread创建Activity

-->performLaunchActivity() new Activity && run attach()

-->Activity#attach()  create Window对象

DecorView的创建

在Code para#1段 L18-L21行的代码调用了Activity的attach()和onCreate();

Activity activity = new Activity();

    -->activity.attach();//回调attach

    -->activity.onCreate();//回调Activity

开发者通常会在onCreate()方法中调用setContentView()设置视图文件。

流程如下:

Activity-->onCreate()-->setContentView()加载视图文件

-->setContentView()-->Window.setContentView()方法,传递视图

-->Window#setContentView()创建了顶级视图DecorView对象

-->为Activity寻找对应的主题文件,解析并添加为DecorView的子View,也就是mContentParent

-->将开发者指定的视图添加到mContentParent

Step1:DecorView 是根Root View,也个FrameLayout,所以mWindow#setContentView()函数中最先将DecorView对象创建出来。

Step2:加载Activity使用的主题文件,并且将该主题作为子View添加到DecorView,这个子View就是mContentParent。

Step3:将我们设置的视图添加为mContentParent的子View,会有一个名为R.id.content的FrameLayout,这个里面才是包含我们设置的视图.

Code para#4

开发者设置的视图添加为子View的下一步,是回调Activity中onContentChanged()方法

当我们在Activity收到onContentChanged()回调的这一刻,说明DecorView已经创建完成

ViewRootImpl的创建

1.1和1.2分别让我们拥有了一个Window对象和一个DecorView对象。

Window对象中包含了DecorView对象,DecorView包含了我们设置的视图文件。

接下来的任务就是把该Window对象传递给WMS

和前两个阶段不同的是,第三阶段是在Activity的onResume()回调中被触发的

在ActivityThread通知完onResume()的下一步调用了makeVisible()方法

makeVisible()方法中,将会调用WindowManager#addView(mDecor)将视图传递给WMS

Code para#5

·  Activity执行完onResume()以后,立刻调用makeVisible()方法准备将视图传递给WMS

·  makeVisible()方法中,调用WindowManager#addView()

·  经过层层调用,最终由进程单例WindowManagerGlobal对象执行addView()方法

·  WindowManagerGlobal#addView()中,创建了本章节主角:ViewRootImpl

·  ViewRootImpl通过binder向wms添加窗口

WindowManagerImpl是WindowManager的最终实现类,它会调用到WindowManagerGlobal#addView()方法

而WindowManagerGlobal是全局单例,每个进程有且只有一个,也就是说

所有的Activity对应的Window都由WindowManagerGlobal进行管理

因此,WindowManagerGlobal会有两个关键集合:mViews和mRoots

mViews是保管着的DecorView的集合,mRoots是保管着ViewRootImpl的集合

保管着ViewRootImpl的集合?

DecorView是每个Activity的跟视图,ViewRootImpl是什么?

//对应一个Activity,关于视图的事件触发都在此

看看ViewRootImpl类中的三个成员变量:

  • mView:DecorView让ViewRootImpl能够在事件来临时控制视图
  • mSurface:让Activity拥有绘图的能力
  • mChoreographer:让ViewRootImpl能够监听VSync信号

这个类几乎集齐了所有与视图相关的成员

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

WindowManagerGlobal创建了ViewRootImpl对象后,把它保存到本地集合mRoots

接着调用ViewRootImpl#setView()方法添加视图,setView()中又调用addToDisplay()方法通过binder向WMS添加窗口

至此,Window对象的创建、DecorView的创建和ViewRootImpl的创建这三大阶段全部完成

我们来总结一下在创建Activity阶段发生的事情

·  Activity中,创建PhoneWindow类型的Window对象

·  Window中,创建DecorView对象,绑定setContentView传入的视图文件

·  调用WindowManager添加视图,准备把视图绑定到WMS

·  创建ViewRootImpl作为最终的执行者,将视图添加WM

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
你可以使用 Android 中的 SurfaceView 和 GestureDetector 来实现视频滑动拖拽的功能。 首先,你需要在布局文件中添加两个 SurfaceView 控件,一个用于显示 display1 的视频,另一个用于显示 display2 的视频。然后,你需要创建两个 SurfaceHolder 对象,分别用于控制两个 SurfaceView 的绘制。 接下来,使用 GestureDetector 来监听用户在 SurfaceView 上的手势操作。当用户滑动手势时,你可以通过计算滑动距离和速度来控制视频的播放进度。 具体实现可以参考以下步骤: 1. 在布局文件中添加两个 SurfaceView 控件: ``` <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:id="@+id/display1" android:layout_width="match_parent" android:layout_height="match_parent" /> <SurfaceView android:id="@+id/display2" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> ``` 2. 在代码中获取 SurfaceView 控件并为其创建 SurfaceHolder 对象: ``` SurfaceView display1 = findViewById(R.id.display1); SurfaceView display2 = findViewById(R.id.display2); SurfaceHolder holder1 = display1.getHolder(); SurfaceHolder holder2 = display2.getHolder(); ``` 3. 使用 GestureDetector 监听手势操作: ``` final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 计算滑动距离和速度,控制视频播放进度 return true; } }); display1.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); display2.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); ``` 4. 在 SurfaceHolder.Callback 中实现视频播放: ``` holder1.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { // 创建 MediaPlayer 对象并设置 SurfaceHolder MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setDisplay(holder); mediaPlayer.setDataSource("video1.mp4"); mediaPlayer.prepare(); mediaPlayer.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 不需要实现 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 释放 MediaPlayer 对象 mediaPlayer.release(); } }); holder2.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { // 创建 MediaPlayer 对象并设置 SurfaceHolder MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setDisplay(holder); mediaPlayer.setDataSource("video2.mp4"); mediaPlayer.prepare(); mediaPlayer.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 不需要实现 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 释放 MediaPlayer 对象 mediaPlayer.release(); } }); ``` 注意,这只是一个简单的示例,你需要根据实际需求进行适当修改。同时也要注意在适当的时候释放资源,避免内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dwyane05

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值