ContentProvider:学习笔记| AS入门(八) 组件篇之ContentProvider - 简书
ContentProvider有存储数据的功能,ContentProvider有两种形式:可以使用现有的内容提供者来读取和操作相应程序中的数据,也可以创建自己的内容提供者给这个程序的数据提供外部访问接口。
从系统提供的Provider访问数据
既然ContentProvider有对外共享数据的功能,换句话说,其他应用程序可以通过ContentProvider对应用中的数据进行增删改查(例如访问通讯录),访问ContentProvider中共享的数据的方法是:
第一步:通过Context 中的getContentResolver()方法实例化一个ContentResolve对象。
第二步:调用该对象的增删改查方法去操作ContentProvider中的数据。
具体内容查看上述链接。
Android跨进程通信:
1.Bundle/Intent传递数据
2.文件共享
3.Messenger
4.AIDL
5.ContentProvider
Bundle 机制:Bundle实现了Parcelable接口,所以他可以方便的在不同进程间传输。
场景:
Activity状态数据的保存与恢复涉及到的两个回调:void onSaveInstanceState (Bundle outState)、void onCreate (Bundle savedInstanceState)
Fragment的setArguments方法:void setArguments (Bundle args)
消息机制中的Message的setData方法:void setData (Bundle data)
Bundle其实就是一个容器,内部使用了Arraymap去存储数据,那么就必然会提供get,put方法
AIDL :Android 进阶7:进程通信之 AIDL 的使用 - 张拭心的博客 shixinzhang - CSDN博客
AIDL(Android 接口定义语言) 是 Android 提供的一种进程间通信 (IPC) 机制。
我们可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。
在 Android 上,一个进程通常无法访问另一个进程的内存, Android 会使用 AIDL 来处理。
通过这种机制,我们只需要写好 aidl 接口文件,编译时系统会帮我们生成 Binder 接口。
AIDL 支持的数据类型共 4 种:
1.Java 的基本数据类型
2.List 和 Map
元素必须是 AIDL 支持的数据类型
Server 端具体的类里则必须是 ArrayList 或者 HashMap
3.其他 AIDL 生成的接口
4.实现 Parcelable 的实体
AIDL 的编写主要为以下三部分:
1.创建 AIDL
创建要操作的实体类,实现Parcelable接口,以便序列化/反序列化
新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件
Make project ,生成 Binder 的 Java 文件
2.服务端
创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法
在onBind()中返回
3.客户端
实现ServiceConnection接口,在其中拿到 AIDL 类
bindService()
我们从Android对aidl文件自动生成的java类中可以看到asInterface()这个接口的实现,大概的意思就是:
如果客户端和服务端在同一个进程下,那么asInterface()将返回Stub对象本身,否则返回Stub.Proxy对象。
Binder机制:Android系统中,涉及到多进程间的通信底层都是依赖于Binder IPC机制。
性能方面
在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。
Binder原理
Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。
Binder运行机制:
注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。
获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。
使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。
序列化:Serializable接口和Parcelable接口
含义:序列化表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
场景:需要通过Intent和Binder等传输类对象就必须完成对象的序列化过程。
Serializable:java提供的接口,将java对象转为字节序列,需要继承接口,为基于磁盘或者网络的对象序列化,调用WriteObject(obj)方法实现。
Parcelable:android提供的接口,基于内存的对象序列化,将对象拆分为可传递的数据类型,基于内存的速度要快于基于磁盘的接口。
serialVersionUID
含义:是Serializable接口中用来辅助序列化和反序列化过程。
注意:原则上序列化后的数据中的serialVersionUID要和当前类的serialVersionUID 相同才能正常的序列化
简单描述Handler:
andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换
Message(消息):需要被传递的消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,最终由Handler处理。
MessageQueue(消息队列):用来存放Handler发送过来的消息,内部通过单链表的数据结构来维护消息列表,等待Looper的抽取。
Handler(处理者):负责Message的发送及处理。
Handler.sendMessage():向消息池发送各种消息事件。
Handler.handleMessage() :处理相应的消息事件。
Looper(消息泵):通过Looper.loop()不断地从MessageQueue中抽取Message,按分发机制将消息分发给目标处理者。
存在关系:
一个Thread只能有一个Looper,可以有多个Handler;
Looper有一个MessageQueue,可以处理来自多个Handler的Message;
MessageQueue有一组待处理的Message,这些Message可来自不同的Handler;
Message中记录了负责发送和处理消息的Handler;
Handler中有Looper和MessageQueue;
UI的线程looper不会卡死(ANR)的原因:
ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。looper采用,epoll+pipe,有消息就依次执行,没消息就block住,让出CPU,等有消息了,epoll会往pipe中写一个字符,把主线程从block状态唤起,主线程就继续依次执行消息。
Android的线程和线程池:
AsyncTask
HandlerThread
IntentService(见前文)
按用途可分为两类:
主线程:一般一个进程只有一个主线程,主要处理界面交互相关的逻辑。
子线程:除主线程之外都是子线程,主要用于执行耗时操作。
按形态可分为三类:
AsyncTask:底层封装了线程池和Handler,便于执行后台任务以及在子线程中进行UI操作。
HandlerThread:一种具有消息循环的线程,其内部可使用Handler。
IntentService:是一种异步、会自动停止的服务,内部采用HandlerThread。
1.AsyncTask Android AsyncTask完全解析,带你从源码的角度彻底理解 - 郭霖的专栏 - CSDN博客
AsyncTask:一种轻量级的异步任务类。AsyncTask的好处:创建异步任务更简单,直接继承它可方便实现后台异步任务的执行和进度的回调更新UI,而无需编写任务线程和Handler实例就能完成相同的任务。
1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
工作原理:
内部有一个静态的Handler对象即InternalHandler:
作用:将执行环境从线程池切换到主线程;通过它来发送任务执行的进度以及执行结束等消息。
注意:必须在主线程中创建
内部有两个线程池:
SerialExecutor:用于任务的排队,默认是串行的线程池
THREAD_POOL_EXECUTOR:用于真正执行任务。
排队执行过程:把参数Params封装为FutureTask对象,相当于Runnable;调用SerialExecutor.execute()将FutureTask插入到任务队列tasks;若没有正在活动的AsyncTask任务,则就会执行下一个AsyncTask任务。执行完毕后会继续执行其他任务直到所有任务都完成。即默认使用串行方式执行任务。
2.HandlerThread
HandlerThread是一个线程类,它继承自Thread,与普通Thread的区别:具有消息循环的效果。内部HandlerThread.run()方法中有Looper,通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。
实现方法步骤:实例化一个HandlerThread对象,参数是该线程的名称;通过HandlerThread.start()开启线程;实例化一个Handler并传入HandlerThread中的looper对象,使得与HandlerThread绑定;利用Handler即可执行异步任务;当不需要HandlerThread时,通过HandlerThread.quit()/quitSafely()方法来终止线程的执行。
Animation(android动画):要点提炼|开发艺术之Animation - 简书
1.View动画(View Animation)/补间动画(Tween animation)
2.逐帧动画(Drawable Animation)
3.属性动画(Property Animation)
View动画:平移动画、缩放动画、旋转动画和透明度动画
通过xml定义:该xml文件创建在res/anim/ 下。
根节点<set>,子节点<translate>、<scale>、<rotate>、<alpha >,分别对应四种View动画:
通过Java代码动态创建具体步骤:
step1:创建TranslateAnimation、RotateAnimation、ScaleAnimation或AlphaAnimation对象。
step2:设置创建的动画对象的属性,如动画执行时间、延迟时间、起始位置、结束位置等。
step3:通过View.startAnimation()方法开启动画。
step4:可通过Animation.setAnimationListener()设置动画的监听器。
Activity的切换效果:
该xml文件创建在res/anim/ 下,Activity默认是有切换效果的,若需要自定义切换效果,需要用到overridePendingTransition(int inAnim, int outAnim)方法。
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
逐帧动画对应类AnimationDrawable:
a.通过xml定义:
该xml文件创建在res/drawable/ 下。根节点<animation-list>,属性android:oneshot表示是否执行一次;子节点<item> 下可设置轮播的图片资源id和持续时间。在xml声明好之后,将它作为View的背景并通过AnimationDrawable来播放即可。
b.通过Java代码动态创建:
AnimationDrawable ad =newAnimationDrawable();
for(inti =0; i <4; i++) {
Drawable drawable = getResources().getDrawable(getResources().getIdentifier("xxx"+ i,"drawable", getPackageName()));
ad.addFrame(drawable,500); }
ad.setOneShot(false);
mView.setBackgroundResource(ad);
ad.start();
属性动画:通过改变对象属性来实现动画,真正改变了view,Android 属性动画:这是一篇很详细的 属性动画 总结&攻略 - 简书
插值器、估值器:Android 动画:你真的会使用插值器与估值器吗?(含详细实例教学) - 简书
实现方式:在res/animator/下可创建属性动画的xml文件。其中,根节点<set>对应AnimatorSet类,子节点<objectAnimator>对应ObjectAnimator类、<animator>对应ValueAnimator类。
ObjectAnimator与 ValueAnimator类的区别:
ValueAnimator 类是先改变值,然后手动赋值给对象的属性从而实现动画;是间接对对象属性进行操作;
ObjectAnimator 类是先改变值,然后自动赋值给对象的属性从而实现动画;是直接对对象属性进行操作;
Android系统的有哪些安全机制:
应用程序签名机制,权限申明机制,访问控制机制,进程通讯机制,内存管理机制。
未完待续..............
网友评论