1.Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
2.Android UIç»å¶ä¹Viewç»å¶çå·¥ä½åç
3.Android UIå¸å±
4.Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
5.车机开发Android SystemUI 架构音量控制详解
6.android ui框架有哪些
Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
Android UI架构的演变:从MVC到MVP、MVVM和MVI
随着Android开发的ossim源码路径发展,为优化代码设计,业界不断探索和实践不同的架构模式,如MVC、MVP、MVVM和MVI,它们的核心目标是“关注点分离”,以提高代码的可维护性、测试性和可读性。最初,所有UI逻辑都集中在Activity中,导致高度耦合,难以管理。 1. MVC:Android的默认设计,将代码划分为Model、View和Controller,尽管解决了Activity代码过载问题,但Activity仍承担了View和逻辑处理的广告排行网站源码双重任务,分离不够彻底。 2. MVP:为了解决MVC的不足,MVP将逻辑分离到Presenter,使用Contract接口定义View和Presenter的交互。但双向依赖仍是其缺点。 3. MVVM:MVVM将Presenter变为ViewModel,使用观察者模式减少双向依赖。DataBinding等工具支持了MVVM的实现,但过度使用可能导致数据流混乱。 4. MVI:MVI强调单数据流,通过ViewState简化View和ViewModel之间的交互。虽然更注重响应式,但过度压缩状态可能导致复杂性。 总的来说,MVP、MVVM和MVI都试图将Activity的职责分解,但每种模式都有其局限性和适用场景。MVVM和MVP本质上相似,而MVI则引入了命令式到响应式的转变。选择哪种架构,应根据项目的具体需求和团队习惯来决定,而不是风行电视源码输出盲目追求新潮。Android UIç»å¶ä¹Viewç»å¶çå·¥ä½åç
è¿æ¯AndroidUIç»å¶æµç¨åæç第äºç¯æç« ï¼ä¸»è¦åæçé¢ä¸Viewæ¯å¦ä½ç»å¶å°çé¢ä¸çå ·ä½è¿ç¨ãViewRoot 对åºäº ViewRootImpl ç±»ï¼å®æ¯è¿æ¥ WindowManager å DecorView ç纽带ï¼Viewçä¸å¤§æµç¨åæ¯éè¿ ViewRoot æ¥å®æçãå¨ ActivityThread ä¸ï¼å½ Activity 对象被å建å®æ¯åï¼ä¼å° DecorView æ·»å å° Window ä¸,åæ¶ä¼å建 ViewRootImpl 对象ï¼å¹¶å° ViewRootImpl 对象å DecorView 建ç«å ³èã
measure è¿ç¨å³å®äº View ç宽/é«ï¼ Measure å®æ以åï¼å¯ä»¥éè¿ getMeasuredWidth å getMeasuredHeight æ¹æ³æ¥è·å View æµéåç宽/é«ï¼å¨å ä¹ææçæ åµä¸ï¼å®çåäºViewçæç»ç宽/é«ï¼ä½æ¯ç¹æ®æ åµé¤å¤ã Layout è¿ç¨å³å®äº View çå个顶ç¹çåæ åå®é ç宽/é«ï¼å®æ以åï¼å¯ä»¥éè¿ getTopãgetBottomãgetLeft å getRight æ¥æ¿å°Viewçå个顶ç¹çä½ç½®ï¼å¯ä»¥éè¿ getWidth å getHeight æ¹æ³æ¿å°Viewçæç»å®½/é«ã Draw è¿ç¨å³å®äº View çæ¾ç¤ºï¼åªæ draw æ¹æ³å®æå View çå 容æè½åç°å¨å±å¹ä¸ã
DecorView ä½ä¸ºé¡¶çº§ View ï¼ä¸è¬æ åµä¸ï¼å®å é¨ä¼å å«ä¸ä¸ªç«ç´æ¹åç LinearLayout ï¼å¨è¿ä¸ª LinearLayout éé¢æä¸ä¸ä¸¤ä¸ªé¨åï¼ä¸é¢æ¯æ é¢æ ï¼ä¸é¢æ¯å 容æ ãå¨Activityä¸ï¼æ们éè¿ setContentView æ设置çå¸å±æä»¶å ¶å®å°±æ¯è¢«å å°å 容æ ä¸çï¼èå 容æ id为 content ãå¯ä»¥éè¿ä¸é¢æ¹æ³å¾å° content:ViewGroup content = findViewById(R.android.id.content) ãéè¿ content.getChildAt(0) å¯ä»¥å¾å°è®¾ç½®ç view ã DecorView å ¶å®æ¯ä¸ä¸ª FrameLayout , View å±çäºä»¶é½å ç»è¿ DecorView ï¼ç¶åæä¼ éç»æ们ç View ã
MeasureSpec 代表ä¸ä¸ªä½çintå¼ï¼é«2ä½ä»£è¡¨ SpecMode ,ä½ä½ä»£è¡¨ SpecSize , SpecMode æ¯ææµé模å¼ï¼è SpecSize æ¯æå¨æç§æµé模å¼ä¸çè§æ ¼å¤§å°ã
SpecMode æä¸ç±»ï¼å¦ä¸æ示ï¼
UNSPECIFIED
EXACTLY
AT_MOST
LayoutParamséè¦åç¶å®¹å¨ä¸èµ·æè½å³å®ViewçMeasureSpecï¼ä»èè¿ä¸æ¥å³å®Viewç宽/é«ã
对äºé¡¶çº§Viewï¼å³DecorViewåæ®éViewæ¥è¯´ï¼MeasureSpecç转æ¢è¿ç¨ç¥æä¸åã对äºDecorViewï¼å ¶MeasureSpecç±çªå£ç尺寸åå ¶èªèº«çLayoutParamså ±åç¡®å®ï¼
对äºæ®éViewï¼å ¶MeasureSpecç±ç¶å®¹å¨çMeasureSpecåèªèº«çLayoutparamså ±åå³å®ï¼
MeasureSpecä¸æ¦ç¡®å®ï¼onMeasureå°±å¯ä»¥ç¡®å®Viewçæµé宽/é«ã
å°ç»ä¸ä¸
å½å View ç宽é«éç¨ wrap_content æ¶ï¼ä¸ç®¡ç¶å®¹å¨ç模å¼æ¯ç²¾ç¡®æ¨¡å¼è¿æ¯æ大模å¼ï¼å View ç模å¼æ»æ¯æ大模å¼+ç¶å®¹å¨çå©ä½ç©ºé´ã
View çå·¥ä½æµç¨ä¸»è¦æ¯æ measure ã layout ã draw ä¸å¤§æµç¨ï¼å³æµéãå¸å±ãç»å¶ãå ¶ä¸ measure ç¡®å® View çæµé宽/é«ï¼ layout ç¡®å® view çæç»å®½/é«åå个顶ç¹çä½ç½®ï¼è draw åå° View ç»å¶å¨å±å¹ä¸ã
measure è¿ç¨è¦åæ åµï¼å¦æåªæ¯ä¸ä¸ªåå§ç view ï¼åéè¿ measure æ¹æ³å°±å®æäºå ¶æµéè¿ç¨ï¼å¦ææ¯ä¸ä¸ª ViewGroup ï¼é¤äºå®æèªå·±çæµéè¿ç¨å¤ï¼è¿ä¼éåè°ç¨ææåå ç´ ç measure æ¹æ³ï¼å个åå ç´ åéå½å»æ§è¡è¿ä¸ªæµç¨ã
å¦ææ¯ä¸ä¸ªåå§ç Viewï¼é£ä¹éè¿ measure æ¹æ³å°±å®æäºæµéè¿ç¨ï¼å¨ measure æ¹æ³ä¸ä¼å»è°ç¨ View ç onMeasure æ¹æ³ï¼View ç±»éé¢å®ä¹äº onMeasure æ¹æ³çé»è®¤å®ç°:
å çä¸ä¸ getSuggestedMinimumWidth å getSuggestedMinimumHeight æ¹æ³çæºç ï¼
å¯ä»¥çå°ï¼ getMinimumWidth æ¹æ³è·åçæ¯ Drawable çåå§å®½åº¦ãå¦æåå¨åå§å®½åº¦ï¼å³æ»¡è¶³ intrinsicWidth > 0ï¼ï¼é£ä¹ç´æ¥è¿ååå§å®½åº¦å³å¯ï¼å¦æä¸åå¨åå§å®½åº¦ï¼å³ä¸æ»¡è¶³ intrinsicWidth > 0ï¼ï¼é£ä¹å°±è¿å 0ã
æ¥ççæéè¦ç getDefaultSize æ¹æ³ï¼
å¦æ specMode 为 MeasureSpec.UNSPECIFIED å³æªæå®æ¨¡å¼ï¼é£ä¹è¿åç±æ¹æ³åæ°ä¼ éè¿æ¥ç尺寸ä½ä¸º View çæµé宽度åé«åº¦ï¼
å¦æ specMode ä¸æ¯ MeasureSpec.UNSPECIFIED å³æ¯æ大模å¼æè 精确模å¼ï¼é£ä¹è¿åä» measureSpec ä¸ååºç specSize ä½ä¸º View æµéåç宽度åé«åº¦ã
çä¸ä¸åæçè¡¨æ ¼ï¼
å½ specMode 为 EXACTLY æè AT_MOST æ¶ï¼View çå¸å±åæ°ä¸º wrap_content æè match_parent æ¶ï¼ç» View ç specSize é½æ¯ parentSize ãè¿ä¼æ¯å»ºè®®çæå°å®½é«è¦å¤§ãè¿æ¯ä¸ç¬¦åæ们çé¢æçãå 为æä»¬ç» View 设置 wrap_content æ¯å¸æViewç大å°å好å¯ä»¥å 裹å®çå 容ã
å æ¤ï¼
å¦ææ¯ä¸ä¸ª ViewGroupï¼é¤äºå®æèªå·±ç measure è¿ç¨ä»¥å¤ï¼è¿ä¼éåå»è°ç¨ææåå ç´ ç measure æ¹æ³ï¼å个åå ç´ åéå½å»æ§è¡ measure è¿ç¨ã
ViewGroup 并没æéå View ç onMeasure æ¹æ³ï¼ä½æ¯å®æä¾äº measureChildrenãmeasureChildãmeasureChildWithMargins è¿å 个æ¹æ³ä¸é¨ç¨äºæµéåå ç´ ã
å¦ææ¯ View çè¯ï¼é£ä¹å¨å®ç layout æ¹æ³ä¸å°±ç¡®å®äºèªèº«çä½ç½®ï¼å ·ä½æ¥è¯´æ¯éè¿ setFrame æ¹æ³æ¥è®¾å® View çå个顶ç¹çä½ç½®ï¼å³åå§å mLeft ï¼ mRight ï¼ mTop ï¼ mBottom è¿å个å¼ï¼ï¼ layout è¿ç¨å°±ç»æäºã
å¦ææ¯ ViewGroup çè¯ï¼é£ä¹å¨å®ç layout æ¹æ³ä¸åªæ¯ç¡®å®äº ViewGroup èªèº«çä½ç½®ï¼è¦ç¡®å®åå ç´ çä½ç½®ï¼å°±éè¦éå onLayout æ¹æ³ï¼å¨ onLayout æ¹æ³ä¸ï¼ä¼è°ç¨åå ç´ ç layout æ¹æ³ï¼åå ç´ å¨å®ç layout æ¹æ³ä¸ç¡®å®èªå·±çä½ç½®ï¼è¿æ ·ä¸å±ä¸å±å°ä¼ éä¸å»å®ææ´ä¸ª View æ ç layout è¿ç¨ã
layout æ¹æ³çä½ç¨æ¯ç¡®å® View æ¬èº«çä½ç½®ï¼å³è®¾å® View çå个顶ç¹çä½ç½®ï¼è¿æ ·å°±ç¡®å®äº View å¨ç¶å®¹å¨ä¸çä½ç½®ï¼
onLayout æ¹æ³çä½ç¨æ¯ç¶å®¹å¨ç¡®å®åå ç´ çä½ç½®ï¼è¿ä¸ªæ¹æ³å¨ View ä¸æ¯ç©ºå®ç°ï¼å 为 View 没æåå ç´ äºï¼å¨ ViewGroup ä¸åè¿è¡æ½è±¡åï¼å®çåç±»å¿ é¡»å®ç°è¿ä¸ªæ¹æ³ã
1.ç»å¶èæ¯ï¼ background.draw(canvas); ï¼ï¼
2.ç»å¶èªå·±ï¼ onDraw ï¼ï¼
3.ç»å¶ childrenï¼ dispatchDraw(canvas) ï¼ï¼
4.ç»å¶è£ é¥°ï¼ onDrawScrollBars ï¼ã
dispatchDraw æ¹æ³çè°ç¨æ¯å¨ onDraw æ¹æ³ä¹åï¼ä¹å°±æ¯è¯´ï¼æ»æ¯å ç»å¶èªå·±åç»å¶å View ã
å¯¹äº View ç±»æ¥è¯´ï¼ dispatchDraw æ¹æ³æ¯ç©ºå®ç°çï¼å¯¹äº ViewGroup ç±»æ¥è¯´ï¼ dispatchDraw æ¹æ³æ¯æå ·ä½å®ç°çã
éè¿ dispatchDraw æ¥ä¼ éçã dispatchDraw ä¼éåè°ç¨åå ç´ ç draw æ¹æ³ï¼å¦æ¤ draw äºä»¶å°±ä¸å±ä¸å±ä¼ éäºä¸å»ãdispatchDraw å¨ View ç±»ä¸æ¯ç©ºå®ç°çï¼å¨ ViewGroup ç±»ä¸æ¯çæ£å®ç°çã
å¦æä¸ä¸ª View ä¸éè¦ç»å¶ä»»ä½å 容ï¼é£ä¹å°±è®¾ç½®è¿ä¸ªæ 记为 trueï¼ç³»ç»ä¼è¿è¡è¿ä¸æ¥çä¼åã
å½å建çèªå®ä¹æ§ä»¶ç»§æ¿äº ViewGroup 并ä¸ä¸å ·å¤ç»å¶åè½æ¶ï¼å°±å¯ä»¥å¼å¯è¿ä¸ªæ è®°ï¼ä¾¿äºç³»ç»è¿è¡åç»çä¼åï¼å½æç¡®ç¥éä¸ä¸ª ViewGroup éè¦éè¿ onDraw ç»å¶å 容æ¶ï¼éè¦å ³éè¿ä¸ªæ è®°ã
åèï¼ãAndroidå¼åèºæ¯æ¢ç´¢ã
Android UIå¸å±
ææ类似çå¸å±<LinearLayout
android:id="@+id/lyApp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="dp"
android:layout_weight="1"
android:background="@drawable/app"
android:gravity="center_horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="left"
android:orientation="vertical" >
<TextView
android:id="@+id/mtxt"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:text="æçå¾å"
android:textColor="#FFFFFF"
android:textSize="dp" />
<TextView
android:id="@+id/mtxt"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="right"
android:text="ç¹å»è¿å ¥ä¸ä¸å½±åå¤ç模å"
android:textColor="#FFFFFF" />
</LinearLayout>
</LinearLayout>
Android HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
HUWUI是Android系统中负责应用可视化元素绘制的核心组件,其架构主要在C++层实现,从Java层接收View绘制信息,通过唯一的渲染线程使用skia技术完成渲染任务。整体上,从应用程序到UI线程,再到渲染线程,形成了清晰的层级关系。
HUWUI的构建主要包括三个核心类,它们分别是:RecordingCanvas、Canvas、RenderNode、RenderProxy、RenderThread、CanvasContext、IRenderPipeline。在Java层,主要涉及两类Canvas,RecordingCanvas用于记录绘制指令,Canvas则是直接用于渲染。RecordingCanvas在构造时创建,而Canvas在调用时创建。神兽大厅牛牛源码这两个类在C++层分别对应SkiaRecordingCanvas和SkiaCanvas,后者直接引用SkCanvas。
在全局循环中,UI线程与渲染线程之间的协同操作至关重要。具体流程包括:新创建Activity后,附着到对应的PhoneWindow,然后调用PhoneWindow的setContentView方法,将View添加到DecorView作为子节点。接着,DecorView与ViewRootImpl对接,完成View的更新与渲染。整个过程包含了measure、layout和draw等复杂子流程。
渲染线程创建与核心对象紧密关联,主要包括RenderProxy、RenderThread和DrawFrameTask。RenderProxy负责Java层信息的衔接,RenderThread作为进程唯一的渲染线程,持有DrawFrameTask和CanvasContext,完成一帧的绘制任务。指令记录流程的核心在于使用C++层的RecordingCanvas将View属性和绘制信息记录到DisplayList中,进而完成指令的群信网站源码渲染。
Surface、ANativeWindow、EGLSurface的创建流程在ViewRootImpl的performTraversals函数中初始化。ReliableSurface的封装和EGL与Skia环境的创建主要在RenderThread的requireGlContext函数中实现。从源码分析,这一过程通常在三个地方调用。
View树与RenderNode树之间的协作关系明确,一个Application进程对应多个Activity,每个Activity与一个PhoneWindow绑定,PhoneWindow持有DecorView,DecorView对应一个ViewRootImpl,而ViewRootImpl与ThreadedRender模块对接。ThreadedRender与C++层的RenderProxy一一对应,RenderProxy持有关键对象,如RenderThread、CanvasContext、DrawFrameTask等。RenderThread是单例模式,进程唯一,负责一帧绘制的逻辑。
在RenderPipeline模块中,关键操作包括makeCurrent、draw和swapBuffers。Native Canvas在这一过程中扮演了桥梁角色,接收Java API调用,而RecordingCanvas完成Op记录,最终DisplayListData存储这些Op。
skia的核心资源主要在三个使用场景中发挥作用,具体细节需深入分析,这些资源对于实现高效、稳定的渲染效果至关重要。
车机开发Android SystemUI 架构音量控制详解
在Android系统中,SystemUI是一个特殊的应用,尽管它的源代码形式类似于普通应用,但它以独特的存在方式运行在系统内部。这个模块以APK文件的形式存在,位于`frameworks/base/packages/SystemUI/`目录下,并安装在`system/priv-app/-SystemUI`路径中。尽管它是一个应用,但它的界面和功能设计使得用户在使用过程中难以将其视为一个传统应用。
SystemUI的核心功能包括提供系统控制界面,例如音量控制、通知管理等。其中,音量控制模块(VolumeUI)在用户操作音量键时负责提供相应的用户界面,并允许设置音量大小和情景模式。VolumeUI的代码主要集中在`SystemUI/volume`目录下,不同模式下音量键触发的UI显示样式会有所不同,包括通话、铃声(通知)、音乐、闹铃、蓝牙输出等。
当音量键触发时,VolumeUI通过系统服务启动,主要经过初始化过程,包括读取配置、实例化UI控件、创建VolumeController控制器等步骤。初始化过程中的关键步骤包括实例化`VolumePanel`,这是一个`Handler`的子类,负责UI的绘制和控制。此过程以Dialog的形式显示UI,确保UI的交互性。`VolumePanel`同时继承了`VolumeUI`的`Pannel`,因此,它不仅负责显示,还控制了UI的显示和关闭。
VolumeUI的架构展示了如何在不同模式下控制音量。当非活动窗口接收到音量键事件时,这些事件通常在`Window`中被处理。系统通过Binder机制将事件信息传递给`MediaSessionService`,然后传递给`AudioService`,最后到达`SystemUI`的`VolumeUI`部分,使得音量控制响应用户操作。
在具体的音量控制过程中,当活动窗口为Launcher桌面时,音量键事件在`PhoneWindow`中被处理。事件分发到`onKeyUp()`和`onKeyDown()`方法,调用`sendAdjustVolumeBy()`方法来调整音量。这些事件最终传递到`MediaSessionService`,进一步通过Binder机制到达`AudioService`,完成音量调整的过程。
总结整个流程,从音量键触发到UI显示和关闭,涉及到多个系统服务和进程之间的通信。通过Binder机制确保了不同组件之间的高效通信和控制。整个控制过程直观且高效,为用户提供了一致且响应迅速的音量控制体验。
android ui框架有哪些
Android UI框架主要包括以下几个部分: 1. Android原生UI框架 Android系统自带的UI框架是开发的基础,它包括了一系列的UI组件,如Activity、Fragment、View、ViewGroup等。这些组件为开发者提供了构建用户界面的基础工具,例如布局、控件、菜单和对话框等。 2. Material Design框架 Material Design是Google推出的设计语言框架,它基于纸质触感的UI设计。在Android开发中,Material Design提供了一系列的UI组件和设计规范,旨在帮助开发者创建美观、现代化的用户界面。这一框架强调动画和过渡效果,提升用户体验。 3. 第三方UI框架和库 除了Android原生和Material Design,还有许多流行的第三方UI框架和库可供使用。例如,React Native可以用于构建高性能的原生界面;Flutter提供了跨平台的开发能力,可以构建美观且响应迅速的用户界面;Jetpack Compose是Android Jetpack的一部分,提供了一种更声明式的UI编程方式。这些框架和库为开发者提供了更多选择和灵活性。 4. 自定义UI框架 开发者也可以根据项目的需求,自行创建定制的UI框架。这通常涉及对原生组件的扩展和定制,或是直接使用开源组件库来实现特定的用户界面需求。通过自定义UI框架,可以实现更为个性化和创新的用户界面设计。 Android UI框架涵盖了原生框架、Material Design规范、第三方库以及自定义框架等多个层面。开发者可以根据项目的需求和团队的技能选择适合的框架来构建用户界面。随着技术的不断发展,Android UI框架也在不断更新和演进,为开发者提供更多选择和可能性。ãAndroidãUIï¼äºï¼Android常ç¨çåºç¡å¸å±å®¹å¨
Android çUI å¯ä»¥å为两类ï¼ä¸ç±»å«åViewGroup容å¨,ä¸ç±»å«åViewè§å¾Viewè§å¾ï¼(TextView,Button,ImageView)é½æ¯å¸¸ç¨å¸¸è§çè§å¾.
ViewGroup容å¨ï¼å é¨å¯ä»¥æ¿è½½ãæ¾ç½®ãæ·»å Viewè§å¾
线æ§å¸å±å°±æ¯ä»å·¦å°å³æä»ä¸å°ä¸æ顺åºæåçä¸ç§å¸å±ãä¸é¢è®²ä¸è®²LinearLayoutçåºç¡å±æ§ã
ç¸å¯¹å¸å±å¨ææ¾åè§å¾ä½ç½®æ¶ï¼æç §æå®çåèç³»æ¥ææ¾åè§å¾çä½ç½®ï¼é»è®¤ä»¥å±å¹å·¦ä¸è§(0,0)ä½ç½®ä½ä¸ºåèç³»ææ¾ä½ç½®
使ç¨layout_below使å¾åé¢ä¸ä¸ªç»ä»¶ä½äºåé¢ä¸ä¸ªç»ä»¶çä¸æ¹
é ålayout_toRightOf使å¾åé¢ä¸ä¸ªç»ä»¶ä½äºåé¢ä¸ä¸ªç»ä»¶çå³æ¹
ç»ä»¶çé»è®¤ä½ç½®é½æ¯å·¦ä¸è§ï¼ç»ä»¶ä¹é´å¯ä»¥éå ãååå±é¥¼ä¸æ ·ï¼ä¸å±åçä¸å± å¯ä»¥è®¾ç½®ä¸ä¸å·¦å³ç对é½ãæ°´å¹³åç´å± ä¸ã设置æ¹å¼ä¸çº¿æ§å¸å±ç¸ä¼¼
åèï¼ Androidä»é¶å ¥é¨å°å®æ(Kotlinç)