Dalvik和Sun JVM
共同点
- 都是解释执行
byte code
(字节码) - 都是每个 OS 进程运行一个
VM
,并执行一个单独的程序 - 在较新版本中(
Froyo / Sun JDK 1.5
)都实现了相当程度的JIT compiler
(即时编译) 用于提速
不同点
-
dvm
执行的是.dex
格式文件,jvm
执行的是.class
文件,android
程序编译完之后生产.class
文件,然后,dex
工具会把.class
文件处理成.dex
文件,然后把资源文件
和.dex
文件等打包成.apk
文件。apk
就是android package的意思。
jvm执行的是.class
文件。 -
dvm
是基于寄存器
的虚拟机 而jvm
执行是基于虚拟栈
的虚拟机。寄存器存取速度比栈快的多
,dvm可以根据硬件实现最大的优化,比较适合移动设备。 -
.class
文件存在很多的冗余信息,dex
工具会去除冗余信息,并把所有的.class
文件整合到.dex
文件中。减少了I/O
操作,提高了类的查找速度。
IPC进程间通信
在一个应用中存在多个进程的情况(不讨论两个应用之间的多进程情况),开启多进程:在Android
的manifests
文件中指定android:process属性
,除此之外没有其他办法
。
进程名:以“:“开头的进程属于当前应用的私有进程,其他的应用不可以和它跑在同一个进程中
,而进程名不以”:“开头的属于全局进程
,其他应用通过shareUID
方式可以和它跑在同一个进程中。Android给每一个进程都分配一个独立的虚拟机,所以运行在不同进程中的四大组件,只要他们之间需要通过内存来共享数据,都会共享失败,这也是多进程所带来的主要影响。
使用多进程会造成问题:
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
-
SharedPreferences
的可靠性下降 -
Application
会多次创建
SharedPreferences
的可靠性降低,因为 SharedPrefrences不支持两个进程同时执行写操作,可能会导致一定几率的数据丢失,这是因为sharedPrefrences
底层是通过读写xml
实现的。
实现跨进程通信的方式:
- 通过Intent来传递数据(通过Bundle来绑定数据)
-
共享文件和
SharedPrefereneces
- 基于Binder的
Messenger
和AIDL
以及Socket
等
序列化:静态成员变量属于类不属于对象,所以不会参与序列化过程,其次transient关键字标记的成员变量不参与序列化过程。 实现了Parcelable
接口的类都是可以直接序列化的,Android中已经实现了parcelable
类的有:Intent
,Bundle
, Bitmap
等,同时 list
和 map
也可以序列化,前提是他们的每个元素都能序列化
。实现了parcelable接口的类都可以通过Intent
和Binder
来传递。
Binder类:实现了IBinder接口,从IPC
角度来说,Binder
是Android
中一种垮进程通信方式,还可以理解为一种虚拟的物理设备,该通信在Linux
中是没有的。Binder
是连接各种manager
(ActivityManager
, windowManager
)和相应的ManagerService
的桥梁。
binder驱动
是整个流程的核心
-
Server
将自己的binder
通过binder驱动
在SM
中进行注册。 -
binder驱动
会建立一个binder实体
的数据节点和实体的引用。 -
Binder驱动
再把名字和引用打包发给SM
。 -
Client
通过binder驱动
拿着他所需要的binder名字
向SM
请求binder
。 -
SM
在自己的查找表
里面找到对应的引用之后再通过binder驱动
返回给client
。
Intent传递数据
根据API文档,
Intent/Bundle
支持传递基本类型
的数据和基本类型的数组
数据,以及String/CharSequence
。而对于其它类型的数据貌似无能为力,其实不然,我们可以在Intent/Bundle
的API中看到Intent/Bundle还可以传递 Parcelable(包裹化,邮包)和Serializable(序列化)类型的数据,以及它们的数组/列表数据。
数据存储
Android数据存储方式:SharedPreferences
,SQLite
,ContentProvider
,File
。
SharedPreferences
键值对的形式存储,底层是xml
文件。并且可以设置权限,是否和其他应用共享该项文件
。 File:Android
分为内部存储
和外部存储
,内部存储中属于APP私有,其他任何应用都不能访问,APP卸载时自动删除。外部存储
又分为两类:公共文件
和私有文件
,私有文件:本属于您的应用且应在用户卸载您的应用时删除的文件。尽管这些文件在技术上可被用户和其他应用访问(因为它们在外部存储上),它们是实际上不向您的应用之外的用户提供值的文件。当用户卸载您的应用时,系统会删除应用外部专用目录中的所有文件。
Android动画
View动画
View动画
注意事项:View动画执行之后并未改变View的真实布局属性值
。切记这一点,譬如我们在Activity
中有一 个Button
在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点 击屏幕下方动画执行之后的Button
是没有任何反应的,而点击原来屏幕上方没有Button
的地方却响应的是点击Button
的事件。
View
动画有四种变换效果,对应Animation
的四个子类:TranslateAnimation
(平移),ScaleAnimation
(缩放),AlphaAnimation
(透明度动画),RotateAnimation
(旋转),一般采用XML的方式来定义动画,可读性更好。
帧动画
对应AnimationDrawale
来使用帧动画,通过XML
来定义个AnimationDrawable
,然后把xml
作为Drawable
作为view
的背景来播放动画就可以了。
注意
帧动画使用比较简单,比较容易引起OOM
,所以尽量避免使用过多尺寸较大的图片
。
属性动画
主要由ValueAnimator
,ObjectAnimator
和AnimatorSet
类实现。
Bitmap加载:
Bitmap
代表一张图片,BitmapFactory
提供了四类方法:decodeFile
,decodeResource
,decodeStream
和 decodeByteArray
加载bitmap
。
Retrofit优点
- 采用
动态代理机制
和反射
,使代码写起来特别简单,看起来也很清晰。 - 可以配合
OkHttp拦截器
,很方便的在header
加token
或者处理cookie
等等。 - 可配合
RxJava
,可以让多个接口调用组合变的更简单。
RequestLayout,invalidate和postInvalidate
-
requestLayout:当
view
确定自身已经不再适合现有的区域时,该view
本身调用这个方法要求parent view
重新调用他的onMeasure
,onLayout
来对重新设置自己位置。
特别的当view
的layoutparameter
发生改变,并且它的值还没能应用到view
上,这时候适合调用这个方法。 -
invalidate:
invalidate
内部最终会调用到performTraversals
(视图绘制的入口),但由于没有设置强制视图重新测量的标志位,所以只会执行onDraw
方法。 -
postInvalidate:是在
非UI线程
使用。
Rxjava
一个词:
异步
。
RxJava
在GitHub
主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在Java VM
上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是RxJava
,概括得非常精准。
在RxJava
的默认
规则中,事件的发出和消费都是在同一个线程
的。在不指定线程的情况下,RxJava
遵循的是线程不变的原则,即:在哪个线程调用subscribe()
,就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到Scheduler
(调度器)。
RxJava
的异步实现,是通过一种扩展的观察者模式
来实现的。
变换(map()
,flatmap()
):
Map
行为:
- 创建了一个新的
Observable
- 创建了一个新的
OnSubscribe
: 其中的call
方法是整个调用链的关键. 它调用了上一级Observable.onSubscribe.call
, 同时, 还将结果通过transform
对 ‘第一步’ 处理后的结果进行变形, 然后将变形后的结果再转发给‘第三步’ 中subscribe(Subscriber…)
中的Subscriber
处理. 那我们马上看一下 ‘第三步’。
Glide优点
- 默认
Bitmap
格式是RGB_565
,内存占用更少
,原因在于Picasso是加载了全尺寸的图片到内存,然后让GPU来实时重绘大小。而Glide加载的大小
和ImageView的大小是一致的
,因此更小。 磁盘缓存
- Picasso和Glide在磁盘缓存策略上有很大的不同。Picasso缓存的是全尺寸的,而
Glide缓存的是跟ImageView尺寸相同
。 -
Glide
可以加载GIF动态图
,而Picasso不能。 - 除了gif动画之外,
Glide
还可以将任何的本地视频解码成一张静态图片。
Material Design
-
TextInputLayout
必须把EditText
包含起来,不能单独使用。
<android.support.design.widget.TextInputLayout
android:id="@+id/til_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
-
FloatingActionButton
继承自ImageView
。 -
NavigationView
实现DrawerLayout
导航菜单界面,通过
app:headerLayout="@layout/navigation_header"
app:menu="@menu/drawer_view"
来设置.
SQLite
public long insert (String table, String nullColumnHack, ContentValues values)
插入数据
参数介绍 :
- 参数①
table
: 数据库中的表名, 要插入数据的表; - 参数②
nullColumnHack
: 该参数是可选的, 数据库表中不允许插入一行空的数据, 插入数据至少有一列不为null
才能插入, 如果后面的values
是null
, 并且不知道列的名称, 那么插入操作会失败, 为了避免这种情况, 就出现了本参数, 为了防止values
为null
的情况; - 参数③
ContentValues
: 相当于一个Map
集合,键是列名,值是对应列名要插入的数据;
插入原则 : 不管第三个 ContentValues
参数是否为null
, 执行insert()
方法都会添加一条记录, 如果values
参数为null
, 会添加一个除主键之外其它字段都为null
的记录;
nullColumnHack参数作用分析SQL
语句 : 在SQL
语句中在表名后面必须跟着一个列名, 例如 " insert into appale_info(name) values("乔帮主")
", 这是values参数不为null的情况下,如果values参数为null, 那么导致表名 "apple_info" 后面的列名也为null, 这样SQL语句就不合法了, 因此这里必须加上一个默认的列名, 以防values参数为null;
HttpURLConnection
设置请求头或响应头
HTTP
请求允许一个key
带多个用逗号分开的values
,但是HttpURLConnection
只提供了单个操作的方法:
setRequestProperty(key,value)
addRequestProperty(key,value)
setRequestProperty
和addRequestProperty
的区别就是,setRequestProperty
会覆盖已经存在的key
的所有values
,有清零重新赋值的作用。而addRequestProperty
则是在原来key的基础上继续添加其他value
。
发送URL请求
建立实际连接之后,就是发送请求,把请求参数传到服务器,这就需要使用outputStream
把请求参数传给服务器:
getOutputStream
获取响应
请求发送成功之后,即可获取响应的状态码,如果成功既可以读取响应中的数据,获取这些数据的方法包括:
getContent
getHeaderField
getInputStream
对于大部分请求来说,getInputStream
和getContent
是用的最多的。
相应的信息头用以下方法获取:
getContentEncoding
getContentLength
getContentType
getDate
getExpiration
getLastModifed
任何网络连接都需要经过socket
才能连接,HttpURLConnection
不需要设置socket
,所以,HttpURLConnection
并不是底层的连接,而是在底层连接上的一个请求。这就是为什么HttpURLConneciton
只是一个抽象类,自身不能被实例化的原因。HttpURLConnection
只能通过URL.openConnection()
方法创建具体的实例。虽然底层的网络连接可以被多个HttpURLConnection
实例共享,但每一个HttpURLConnection实例只能发送一个请求
。请求结束之后,应该调用HttpURLConnection
实例的InputStream
或OutputStream
的close()
方法以释放请求的网络资源,不过这种方式对于持久化连接没用。对于持久化连接
,得用disconnect()
方法关闭底层连接的socket
。
ViewStub、include、merge
Json
一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。
JSON
采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为。
优点:
-
数据格式比较简单,易于读写,格式都是压缩的,占用带宽小
; 易于解析
- 支持多种语言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等服务器端语言,便于服务器端的解析;
- 因为JSON格式能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,且完成任务不变,并且易于维护。
缺点:
- 没有XML格式这么推广的深入人心和喜用广泛,没有XML那么通用性;
- JSON格式目前在Web Service中推广还属于初级阶段
Android中Parcelable和Serializable
作用:
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。简单易用,
这种方法的缺点是使用了反射
,序列化的过程较慢
。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收
。
而Android的Parcelable的设计初衷是因为
Serializable
效率过慢,为了在程序内不同组件间以及不同Android
程序间(AIDL
)高效的传输数据而设计,这些数据仅在内存中存在
,Parcelable
是通过IBinder
通信的消息的载体。
效率
Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化
从上面的设计上我们就可以看出优劣了。
- 整个读写全是在内存中进行,所以效率比JAVA序列化中使用外部存储器会高很多;
- 读写时是4字节对齐的
- 如果预分配的空间不够时,会一次多分配50%;
- 对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。后者 是通过
flatten_binder()
和unflatten_binder()
实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。
后期持续更新。。。。。。