- 博客(49)
- 资源 (79)
- 收藏
- 关注
原创 Android调用系统相机程序
一、请求相机功能声明你的应用依赖于相机,请在清单文件中添加 uses-feature 代码:<manifest ... > <uses-feature android:name="android.hardware.camera" android:required="true" /> ...</manifest>如果你的应用使用相机,但不需要相机也可以正常运作,应将 android:required 设为 fa.
2021-01-27 13:32:16 3567
原创 服务端高并发分布式架构演进之路
一、概述本文以淘宝作为例子,介绍从一百个到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知,文章最后汇总了一些架构设计的原则。特别说明:本文以淘宝为例仅仅是为了便于说明演进过程可能遇到的问题,并非是淘宝真正的技术演进路径二、基本概念在介绍架构之前,为了避免部分读者对架构设计中的一些概念不了解,下面对几个最基础的概念进行介绍:分布式系统中的多个模块在不同服务器上部署,即可称为分布式系统,如Tomcat和数据库分别部署在不同的服务
2020-09-11 14:34:45 704
原创 Android视图SurfaceView的实现原理分析
在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。普通的Android控件,例如TextView、Button和CheckBox等,它们都是将自己的UI绘制在宿主窗口的绘图表面之上,这意味着它们的UI是在应用程序的主线
2020-09-08 15:36:08 2698 2
原创 Android控件TextView的实现原理分析
在前面我们分析了WindowManagerService服务的实现。同时,又分析了窗口的组成。简单来说,窗口就是由一系列的视图按照一定的布局组织起来的。实际上,每一个视图都是一个控件,这些控件可以将自己的UI绘制在窗口的绘图表面上,同时还可以与用户进行交互,即获得用户的键盘或者触摸屏输入。由于Android系统提供的控件比较多,因此我们只能挑一个比较有代表的控件进行分析。这个比较有代表性的控件便是TextView,其它的一些基础控件,例如Button、EditText和CheckBox等,都是直接或者间接
2020-09-08 13:58:13 556
原创 硬件加速动画执行过程分析
通常我们说一个系统不如另一个系统流畅,说的就是前者动画显示不如后者流畅,因此动画显示流畅程度是衡量一个系统流畅性的关键指标。为什么这样说呢?这是因为流畅的动画显示需要60fps的UI刷新速度,然而这却不是一个容易达到的速度。Android 5.0通过引入Render Thread尽最大努力提升动画显示流畅性。在前面我们提到了Render Thread对动画显示的两个优化。第一个优化是在动画显示期间,临时将动画的目标View的Layer Type设置为LAYER_TYPE_HARDWARE,这样就可以使得目
2020-09-08 11:28:43 548
原创 Display List渲染过程分析
在硬件加速渲染环境中,Android应用程序窗口的UI渲染是分两步进行的。第一步是构建Display List,发生在应用程序进程的Main Thread中;第二步是渲染Display List,发生在应用程序进程的Render Thread中。Display List的渲染不是简单地执行绘制命令,而是包含了一系列优化操作,例如绘制命令的合并执行。Android应用程序窗口的Root Render Node的Display List,包含了Android应用程序窗口所有的绘制命令,因此我们只要对Root
2020-09-08 11:04:28 1491 1
原创 Display List构建过程分析
在硬件加速渲染环境中,Android应用程序窗口的UI渲染是分两步进行的。第一步是构建Display List,发生在应用程序进程的Main Thread中;第二步是渲染Display List,发生在应用程序进程的Render Thread中。Display List是以视图为单位进行构建的,因此每一个视图都对应有一个Display List。这里说的Display List与Open GL里面的Display List在概念上是类似的,不过是两个不同的实现。Display List的本质是一个缓冲区,
2020-09-07 15:25:13 10241
原创 预加载资源地图集服务(Asset Atlas Service)分析
我们知道,Android系统在启动的时候,会对一些系统资源进行预加载。这样不仅使得应用程序在需要时可以快速地访问这些资源,还使得这些资源能够在不同应用程序之间进行共享。在硬件加速渲染环境中,这些预加载资源还有进一步优化的空间。Android系统提供了一个地图集服务,负责将预加载资源合成为一个纹理上传到GPU去,并且能够在所有的应用程序之间进行共享。资源预加载是发生在Zygote进程的,然后Zygote进程fork了应用程序进程,于是就使得预加载的资源可以在Zygote进程与所有的应用程序进程进行共享。这种
2020-09-07 13:25:47 1007
原创 Android UI硬件加速环境初始化过程分析
在Android应用程序中,我们是通过Canvas API来绘制UI元素的。在硬件加速渲染环境中,这些Canvas API调用最终会转化为Open GL API调用(转化过程对应用程序来说是透明的)。由于Open GL API调用要求发生在Open GL环境中,因此在每当有新的Activity窗口启动时,系统都会为其初始化好Open GL环境。Open GL环境也称为Open GL渲染上下文。一个Open GL渲染上下文只能与一个线程关联。在一个Open GL渲染上下文创建的Open GL对象一般来说只能
2020-09-07 11:18:39 413
原创 Android UI硬件加速简要介绍
Android系统的UI从绘制到显示到屏幕是分两步进行的:第一步是在Android应用程序进程这一侧进行的;第二步是在SurfaceFlinger进程这一侧进行的。前一步将UI绘制一个图形缓冲区中,并且将该图形缓冲区交给后一步进行合成以及显示在屏幕中。其中,后一步的UI合成一直都是以硬件加速方式完成的。在支持Android应用程序UI硬件加速渲染之前,Android应用程序UI的绘制是以软件方式进行的:在Android应用程序进程这一侧,每一个窗口都关联有一个Surface。每当窗口需要绘制UI时,就
2020-09-07 10:49:24 626
原创 显示窗口动画的原理分析
在Android系统中,Activity是以堆栈的形式组织在ActivityManagerService服务中的。与Activity类似,Android系统中的窗口也是以堆栈的形式组织在WindowManagerService服务中的,其中,Z轴位置较低的窗口位于Z轴位置较高的窗口的下面。应用程序进程中的每一个Activity组件在Activity管理服务ActivityManagerService中都对应有一个ActivityRecord对象。Activity管理服务ActivityManagerSer
2020-09-01 17:20:13 633
原创 切换Activity窗口(App Transition)的过程分析
在Android系统中,同一时刻只有一个Activity组件是处于激活状态的,因此,当ActivityManagerService服务激活了一个新的Activity组件时,它就需要通知WindowManagerService服务将该Activity组件的窗口显示出来,这会涉及到将焦点和屏幕等资源从前一个激活的Activity组件切换到后一个激活的Activity组件的过程。Activity窗口的切换操作是在新激活的Activity组件的启动过程进行的。具体来说,就是在前一个激活的Activity组件进入到
2020-08-31 11:47:33 1761 2
原创 显示Activity组件的启动窗口(Starting Window)的过程分析
在Android系统中,Activity组件在启动之后,并且在它的窗口显示出来之前,可以显示一个启动窗口。这个启动窗口可以看作是Activity组件的预览窗口,是由WindowManagerService服务统一管理的,即由WindowManagerService服务负责启动和结束。Activity组件的启动窗口是由ActivityManagerService服务来决定是否要显示的。如果需要显示,那么ActivityManagerService服务就会通知WindowManagerService服务来为正
2020-08-27 18:17:18 1883
原创 计算窗口Z轴位置的过程分析
在Android系统中,无论是普通的Activity窗口,还是特殊的输入法窗口和壁纸窗口,它们都是被WindowManagerService服务组织在一个窗口堆栈中的,其中,Z轴位置较大的窗口排列在Z轴位置较小的窗口的上面。有了这个窗口堆栈之后,WindowManagerService服务就可以按照一定的规则计算每一个窗口的Z轴位置了。基于窗口堆栈来计算窗口的Z轴位置是比较有意思的。按照一般的理解,应该是先计算好窗口的Z轴位置,然后再按照Z轴位置的大小来将各个窗口排列在堆栈中。但是,事实上,窗口是按照其它
2020-08-27 16:42:30 669
原创 对壁纸窗口(Wallpaper Window)的管理分析
在Android系统中,壁纸窗口和输入法窗口一样,都是一种特殊类型的窗口,而且它们都是喜欢和一个普通的Activity窗口缠绵在一起。大家可以充分地想象这样的一个3W场景:输入法窗口在上面,壁纸窗口在下面,Activity窗口夹在它们的中间。一个Activity窗口如果需要显示壁纸,那么它必须满足以下两个条件:背景是半透明的,例如,它在AndroidManifest.xml文件中的android:theme属性设置为Theme.Translucent:<activity android:na
2020-08-27 16:17:41 1439
原创 对输入法窗口(Input Method Window)的管理分析
在Android系统中,输入法窗口是一种特殊类型的窗口,它总是位于需要使用输入法的窗口的上面。也就是说,一旦WindowManagerService服务检测到焦点窗口需要使用输入法,那么它就会调整输入法窗口在窗口堆栈中的位置,使得输入法窗口位于在焦点窗口的上面,这样用户可以通过输入法窗口来录入字母或者文字。在Android系统中,除了输入法窗口之外,还有一种窗口称为输入法对话框,它们总是位于输入法窗口的上面。Activity窗口、输入法窗口和输入法对话框的位置关系如图所示:WindowManagerS
2020-08-27 15:44:59 1463
原创 窗口的组织方式
在Android系统中,Activity是以堆栈的形式组织在ActivityManagerService服务中的。与Activity类似,Android系统中的窗口也是以堆栈的形式组织在WindowManagerService服务中的,其中,Z轴位置较低的窗口位于Z轴位置较高的窗口的下面。应用程序进程中的每一个Activity组件在Activity管理服务ActivityManagerService中都对应有一个ActivityRecord对象。Activity管理服务ActivityManagerSer
2020-08-27 11:49:07 551
原创 计算Activity窗口大小的过程分析
在Android系统中,Activity窗口的大小是由WindowManagerService服务来计算的。WindowManagerService服务会根据屏幕及其装饰区的大小来决定Activity窗口的大小。一个Activity窗口只有知道自己的大小之后,才能对它里面的UI元素进行测量、布局以及绘制。一般来说,Activity窗口的大小等于整个屏幕的大小,但是它并不占据着整块屏幕。为了理解这一点,我们首先分析一下Activity窗口的区域是如何划分的。我们知道,Activity窗口的上方一般会有一个
2020-08-27 10:25:48 1043
原创 WindowManagerService的简要介绍
在Android系统中,对系统中的所有窗口进行管理是窗口管理服务WindowManagerService的职责。在Android系统中,同一时刻,只有一个Activity窗口是激活的,但是,对于WindowManagerService服务来说,这并不意味着它每次只需要管理一个Activity窗口,例如,在两个Activity窗口的切换过程中,前后两个Activity窗口实际上都是可见的。即使在只有一个Activity窗口是可见的时候,WindowManagerService服务仍然需要同时管理着多个窗口,这
2020-08-27 09:41:30 1660
原创 Measure、Layout和Draw过程分析
Android应用程序窗口的绘图表面在创建完成之后,我们就可以从上到下地绘制它里面的各个视图了,即各个UI元素了。不过在绘制这些UI元素之前,我们还需要从上到下地测量它们实际所需要的大小,以及对它们的位置进行合适的安排,即对它们进行合适的布局。Android应用程序窗口请求SurfaceFlinger服务创建了一个绘图表面之后,就可以接着请求为该绘图表面创建图形缓冲区,而当Android应用程序窗口往这些图形缓冲区填充好UI数据之后,就可以请求SurfaceFlinger服务将它们渲染到硬件帧缓冲区中去,
2020-08-27 09:22:45 845
原创 Surface的创建过程分析
WindowManagerService服务会为应用程序窗口创建一个到SurfaceFlinger服务的连接。有了这个连接之后,WindowManagerService服务就可以为应用程序窗口创建绘图表面了,以便可以用来渲染窗口的UI。每一个在C++层实现的应用程序窗口都需要有一个绘图表面,然后才可以将自己的UI表现出来。这个绘图表面是需要由应用程序进程请求SurfaceFlinger服务来创建的,在SurfaceFlinger服务内部使用一个Layer对象来描述,同时,SurfaceFlinger服务会
2020-08-26 17:05:54 1640 2
原创 Android应用程序窗口(Activity)与WindowManagerService服务的连接过程
Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求WindowManagerService为其增加一个WindowState对象,用来描述它的窗口状态。我们从两方面来看Activity组件与WindowManagerService服务之间的连接。一方面是从Activity组件到WindowManagerService服务的连接,另一方面是从WindowManagerService服务到Activity组件的连接。从Activit
2020-08-26 16:17:10 531
原创 View的创建过程
每一个Activity组件都有一个关联的Window对象,用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个View对象,用来描述应用程序窗口的视图。应用程序窗口视图是真正用来实现UI内容和布局的,也就是说,每一个Activity组件的UI内容和布局都是通过与其所关联的一个Window对象的内部的一个View对象来实现的。应用程序窗口内部所包含的视图对象的实际类型为DecorView。DecorView类继承了View类,是作为容器(ViewGroup)来使用的,它的实现如图所示:每一个应用
2020-08-26 14:23:56 948
原创 Window的创建过程分析
每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。Activity只不过是一个高度抽象的UI组件,它的具体UI实现其实是由其它的一系列对象来实现的。在PHONE平台上,与Activity组件所关联的窗口对象的实际类型为PhoneWindow,后者是从Window类继承下来的。Activity和Window的类关系图:Window和PhoneWindow的类关系图:与Activity组件所关联的一个PhoneWi
2020-08-26 13:48:47 229
原创 Context的创建过程分析
Android应用程序窗口在运行的过程中,需要访问一些特定的资源或者类。这些特定的资源或者类构成了Android应用程序的运行上下文环境,Android应用程序窗口可以通过一个Context接口来访问它,这个Context接口也是我们在开发应用程序时经常碰到的。Android应用程序窗口的运行上下文环境是通过ContextImpl类来描述的,即每一个Activity组件都关联有一个ContextImpl对象。Activity组件通过其父类ContextThemeWrapper和ContextWrapp
2020-08-26 11:48:57 321
原创 Android资源管理框架:查找过程
在Android系统中,每一个应用程序一般都会配置很多资源,用来适配不同密度、大小和方向的屏幕,以及适配不同的国家、地区和语言等等。这些资源是在应用程序运行时自动根据设备的当前配置信息进行适配的。这也就是说,给定一个相同的资源ID,在不同的设备配置之下,查找到的可能是不同的资源。这个资源查找过程对应用程序来说,是完全透明的。Android资源管理框架实际就是由AssetManager和Resources两个类来实现的。其中,Resources类可以根据ID来查找资源,而AssetManager类根据文件名
2020-08-25 15:20:03 822
原创 Android资源管理框架:Asset Manager的创建过程
Android应用程序在运行的过程中,是通过一个称为AssetManager的资源管理器来读取打包在APK文件里面的资源文件的。应用程序的每一个Activity组件都关联有一个ContextImpl对象,这个ContextImpl对象就是用来描述Activity组件的运行上下文环境的。Activity组件是从Context类继承下来的,而ContextImpl同样是从Context类继承下来的。我们在Activity组件调用的大部分成员函数都是转发给与它所关联的一个ContextImpl对象的对应的成员函
2020-08-25 14:09:41 889
原创 Android资源管理框架:编译和打包
在一个APK文件中,除了有代码文件之外,还有很多资源文件。这些资源文件是通过Android资源打包工具aapt(Android Asset Package Tool)打包到APK文件里面的。在打包之前,大部分文本格式的XML资源文件还会被编译成二进制格式的XML资源文件。只有那些类型为res/animator、res/anim、res/color、res/drawable(非Bitmap文件,即非.png、.9.png、.jpg、.gif文件)、res/layout、res/menu、res/values和
2020-08-25 13:29:26 461
原创 Android系统中的广播(Broadcast)机制
在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制;这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用。在Android系统中,为什么需要广播机制呢?如果是两个组件位于不同的进程当中,那么可以用Binder机制来实现,如果两个组件是在同一个进程中,那么它们之间可以用来通信的方式就更多了,这样看来,广播机制似乎是多余的。然而,广播机制却是不可替代的,它和Binder机制不一样的地方在于,广播的发送者和接收者事先是不需要知道
2020-08-14 14:35:05 1096
原创 Android应用程序绑定服务(bindService)的过程
Android应用程序组件Service与Activity一样,既可以在新的进程中启动,也可以在应用程序进程内部启动。本文将要介绍在应用程序内部绑定Service的过程,这是一种在应用程序进程内部启动Service的方法。Step 1. ContextWrapper.bindService这个函数定义在frameworks/base/core/java/android/content/ContextWrapper.java文件中:public class ContextWrapper extends
2020-08-14 11:44:57 1828
原创 Android应用程序启动过程
Step 1. Launcher.startActivitySafely在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。Launcher的源代码工程在packages/apps/Launcher2目录下,负责启动其它应用程序的源代码实现在src/com/android/launcher2/Launcher.java文
2020-08-13 14:39:19 459
原创 Android处理崩溃的一些实践
对于任何程序来说,崩溃都是一件很难避免的事情,当然Android程序也不例外。在Android程序中,引起崩溃的多属于运行时异常或者错误,对于这些异常我们很难做到类似Checked Exception那样显式捕获,因而最终导致了程序崩溃。本文讲介绍一些如何处理崩溃的实践,比如收集崩溃的stacktrace,甚至如何避免出现程序已停止的对话框。如何收集崩溃信息收集崩溃信息,可以更好的修复问题,增强程序的稳定性。Android中的崩溃收集沿用了Java的收集机制,实现起来比较简单。1、实现Uncaugh
2020-08-11 17:01:06 177
原创 正确配置你的 Android 项目
gitignore当你新建 Android 项目时,默认会生成 gitignore 文件,但并没有包含所有必要的规则。这里推荐大家使用 gitignore.io网站,只需要输入关键字,比如 Android, Intellij 再点击按钮,就能得到一个标准的 gitignore 文件啦。tools folder如果你的项目有很多的第三方脚本,规则列表或其他的文件,不要随意的将它们放在 root 目录下,新建一个 tools 文件夹,把它们都放在里面。通常你可以放入自定义的 gradle 脚本文件,
2020-08-11 16:45:07 202
原创 Android中的图片压缩技术详解
在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩。前者是在不改变图片尺寸的情况下,改变图片的存储体积,而后者则是降低图像尺寸,达到相同目的。质量压缩逻辑在Android中,对图片进行质量压缩,通常我们的实现方式如下所示:ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//quality 为0~100,0表示最小体积,100表示最高质量,对应体积也是最大
2020-08-10 16:30:29 1489
原创 19条人机交互定律
美即易用性效应美的东西看起来会比不美的好用,人们会根据产品的外观来判断它们好不好用多尔蒂的阈值人机交互的时间小于400ms的时候生产力会飙升,在400ms内及时反馈才能维持住用户的注意力并提高效率费茨定律到达目标的时间是目标的区域距离和大小的函数,距离越大,尺寸越小,所需要的时间就越长这个法则特别适用于设计按钮,让按钮更易于找到和选择希克定律选择的数量越多,越复杂,决策所需要的时间越长通过突出显示推荐选项,避免过载的信息让用户无法抉择雅各布定律用用户熟知习惯的使用模式设计产品,
2020-08-07 18:24:20 605
原创 Handler问题总结
一、Handler是什么Android定义的一套 子线程与主线程间通讯的消息传递机制 。二、Handler有什么用把子线程中的UI更新信息,传递给主线程(UI线程),以此完成UI更新操作。三、为什么要用Handler,不用行不行不行,Handler是android在设计之初就封装了的一套消息创建、传递、处理机制。Android要求我们在主线程中更新UI,是要求,建议,不是规定,硬要在子线程中更新UI,也是可以的!比如,在一个子线程中,创建一个对话框:而我们平时在子线程中更新UI报错是这
2020-08-07 10:48:17 698 1
原创 RecyclerView深入研究
预取功能(Prefetch)这个功能是rv在版本25之后自带的,也就是说只要你使用了25或者之后版本的rv,那么就自带该功能,并且默认就是处理开启的状态,通过LinearLayoutManager的setInitialItemPrefetchCount()我们可以手动控制该功能的开启关闭,但是一般情况下没必要也不推荐关闭该功能。我们都知道android是通过每16ms刷新一次页面来保证ui的流畅程度,现在android系统中刷新ui会通过cpu产生数据,然后交给gpu渲染的形式来完成,从上图可以看出当
2020-08-06 15:50:12 492
原创 快速排序
同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的。不同的是,冒泡排序在每一轮只把一个元素冒泡到数列的一端,而快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分。这种思路就叫做分治法。假如给定8个元素的数列,一般情况下冒泡排序需要比较8轮,每轮把一个元素移动到数列一端,时间复杂度是O(n^2)。而快速排序的流程是什么样子呢?如图所示,在分治法的思想下,原数列在每一轮被拆分成两部分,每
2020-07-30 11:29:24 278
原创 翻转二叉树
2015年,Homebrew 的作者 Max Howell 在 Twitter 上发布了一条消息:brew作者在Google挂了,还发twitter说,Google面试官说:对不起,虽然我们全公司的人都在用你的brew但是你竟然不能写出反转二叉树的代码,所以,滚吧。你可以在leetcode上做这道题,有一种答案只需要8行代码。这个题目的难度属于Easy,根据leetcode的定义,如果Easy难度的题目无法在面试中答出来,确实是拿不到Offer的。https://leetcode-cn.com/pr
2020-07-30 09:58:33 7307
原创 深入理解HashMap
在 Java 中,最常用的数据类型是 8 中基本类型以及他们的包装类型以及字符串类型,其次应该就是 ArrayList和HashMap了吧。HashMap存的是键值对类型的数据,其存储和获取的速度快、性能高,是非常好用的一个数据结构。结构先来看一下整个 Map家族的集成关系图,一看东西还不少,但其他的可能都没怎么用过,只有 HashMap最熟悉。以下描述可能不够专业,只为简单的描述 HashMap的结构,请结合下图进行理解。HashMap主体上就是一个数组结构,每一个索引位置英文叫做一个 b.
2020-07-27 10:49:18 292
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人