<疯狂Android讲义>阅读笔记(4)

java程序的国家化主要通过如下三个类完成
1、java.util.ResourceBundle:用于加载一个国家、语言资源包。
2、java.util.locale:用于封装一个特定的国家/区域、语言环境
3、java.text.MessageFormat:用于格式化带占位符的字符串。

Bitmap和BitmapFactory
bitmap代表一张位图,BitmapDrawable里封装的图片就是一个Bitmap对象。开发者为了把一个Bitmap对象封装成BitmapDrawable对象,可以调用BitmapDrawable的构造器。
BitmapFactory是一个工具类,它用于提供大量的方法,这些方法可用于从不同数据源解析、创建Bitmap对象,包括如下方法:
decodeByteArray(byte[]data.int offset,int length):从指定字节数组的offset位置开始,将长度为length的字节数据解析成bitmap对象。
decodefile:从pathname指定的文件中解析,创建Bitmap对象。
decodefileDescriptor:用于fileDescriptor对应的文件中解析、创建Bitmap对象。
decodeResource(Resoucese res,int id);用于根据给定的资源id从指定资源中解析、创建Bitmap对象。
decodeStream(inputStream is):用于从制定输出流中解析、创建Bitmap对象。
安卓为Bitmap提供了两个方法来判断它是否已回收,以及强制Bitmap回收自己。
boolean isRecycled():返回该Bitmap对象是否已被回收。
void  recycle();强制一个Bitmap对象立即回收自己。

安卓的绘图与此类似。
安卓的绘图应该继承View组件,并重写它的onDraw方法即可。

利用双缓冲实现画图板
如果程序每次都只是从上次拖动事件的发生点绘一条直线到本次拖动事件的发生点,那么用户前面绘制的就会丢失。为了保留用户绘制的内容,程序要借助于双缓冲技术。
所谓双缓冲技术:当程序需要在指定View上进行绘制时,程序并不直接绘制到该View组件上,而是先绘制到一个内存中的Bitmap图片上,等到内存中的Bitmap绘制好之后,再一次性将bitmap会知道View组件上。

使用Matrix控制变换。
Matrix是安卓体on个的一个矩阵工具类,它本身并不能对图像或组件进行交换,但它可与其他API结合来控制图形、组件的变换。
使用matrix控制图像或组件变换的步骤如下:
1、获取Matrix对象,该Matrix对象既可新创建,也可直接获取其他对象内封装的Matrix
2、调用Matrix的方法进行平移、旋转、缩放、倾斜等。
3、将程序对Matrix所做的变换应用到指定图像或组件。

使用drawBitmapMesh扭曲图像
canvas提供了一个drawBitmapMesh方法,这方法可以对bitmap进行扭曲。

drawbitmapMesh方法关键参数
bitmap:指定需要扭曲的源位图。
meshwidth:该参数控制在横向上把该源位图划分成多少格。
meshheight:该参数控制在纵向上把该源位图划分成多少格。
verts:该参数是一个长度为(meshwidth+1)*(meshheight+1)*2的数组,它记录了扭曲后的位图各顶点的位置。虽然它是个一维数组,实际上它记录的数据是形如(x,y)格式的数据,这些数组元素控制对bitmap位图的扭曲效果。
vertoffset:控制verts数组中从第几个数组元素开始对bitmap进行扭曲。

使用shader填充图形
前面介绍Paint提到该shader包含了一个setshader(shaders)方法,该方法控制画笔的渲染效果:安卓不仅可以使用颜色来填充图形(包括前面介绍的矩形、椭圆、圆形等几何图形),也可以使用shader对象指定的渲染效果来填充图形。
shaderl本身是一个抽象类,它提供了如下实现类。
1、bitmapshader:使用位图平铺的渲染效果。
2、LinearGradient:使用线性渐变来填充图形
3、RadialGradient: 使用圆形渐变来填充图形
4、SweepGradient:使用角度渐变来填充图形
5、ComposeShader:使用组合渲染效果来填充图形 

使用sharedPreferences
有些时候,应用程序有少量的数据需要保存,而且这些数据的格式很简单:都是普通的字符串、标量类型的值等,比如应用程序的各种配置信息(如是否打开音效,是否使用震动效果等,小游戏的玩家积分)等,对于这种数据,安卓提供了sharedpreferences进行保存

sharedpreferences保存的数据主要是类似于配置信息格式的数据,因此它保存的数据主要是简单类型的key-value对。
sharedpreferences接口主要负责读取应用程序的Preferences数据,它提供了如下方法来访问key-value对。
boolean contain(String key):判断sharedPreferences是否包含特定key的数据。
abstract Map<String ,?> getAll():获取SharedPreferences数据里全部的key-value对。
boolean getXxx(String key ,xxx defvalue):获取sharedPreferences数据里指定key指定的value。如果该key 不能存在,返回默认值defvalue。其中xxx可以是boolean,float,int,long,String等各种基本类型的值。

sharedPreferences本身是一个接口,程序无法直接创建SharedPreferences实例,只能通过context提供的getsharedPreferences(String name ,int mode)方法来获取sharedPreferences实例。该方法的第二个参数支持如下几个值
Context.MODE_PRIVATE :指定该sharedPreferences数据只能被本应用程序读、写
Context..MODE_WORLD_READBLE:指定该sharedPreferences数据能被其他应用程序读,但不能写。
Context..MODE_WORLD_WRITEBLE:指定该sharedPreferences数据能被其他应用程序读、写。

sharedPreferences接口本身并没有提供写入数据的能力,而是通过sharedPreferences的内部接口,sharedPreferences调用edit()方法即可获取它所对应的editor对象。

读、写SD上的文件请按如下步骤进行:
1、调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。例如使用如下代码:
Environment.getExteranlStorageState().equals(Environment.Media_Mounted)
2、调用Environment的getExternalStorageeDirectory()方法获取外部存储器,也就是SD卡的目录
3、使用fileinputStream fileoutputStream,fileReader或filewriter读、写SD卡里的文件
应用程序读、写SD卡的文件有如下两个注意点:
手机上应该已插入SD卡。对于模拟器来说,可通过mksdcard命令来创建虚拟存储卡,关于虚拟卡的管理参考第1章。
为了读、写SD卡上的数据,必须在应用程序的清单文件中添加读、写SD卡的权限

安卓系统继承了一个轻量级的数据库,SQLite。SQLite只是一个嵌入式的数据库引擎。
SQLite数据库只是一个文件。
从本质上看,SQLite的操作方式只是一种更为边界的文件操作。后面我们会看到,当应用程序创建或打开一个SQLite数据库时,其实只是打开一个文件准备读写。

SQLiteOpenHelper是安卓一个管理数据库的工具类,可用于管理数据库的创建和版本更新。一般的用法是创建SQLiteOpenHelper的子类,并扩展它的onCreate和onUpgrade方法。

synchronizedSQliteDataBase getReadableDatabase():以读写的方式打开数据库对应的数据库对象
synchronized SQliteDataBase getReadableDatabase():以写的方式打开数据库对应的数据库对象
abstract void onCreate(SQLiteDataBase db):当第一次创建数据库时回调该方法。
abstract void onUpgrade(SQLiteDataBase db ,int oldVersion,int newVersion):当数据库版本更新时回调该方法。
synchronized void close() :关闭所有打开的SQlitDataBase

gesture 
所谓手势,其实是指用户手机或触摸笔在触摸屏上的连续触碰行为。比如,在屏幕上从左至右画出一个动作,就是手势。手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。
对于第一种手势行为而言,安卓提供了手势检测,并为手势检测提供了相应的监听器。
对于第二种行为,安卓允许开发者添加手势,并提供了相应的API识别用户手势。

使用安卓的手势检测只需两个步骤。
1、创建一个GestureDetector对象。创建该对象时必须实现一个GestureDetector.OnGestureListenter监听器实例。
2、为应用程序的activity的touchevent事件绑定监听器,在事件处理中指定把activity(或特定组件)上的touchevent事件就会交给GestureDetector处理,而GestureDetetor就会检测是否出发了特定的手势动作。

安卓除了提供手势检测之外,还允许应用程序把用户手势(多个持续的触摸事件在屏幕上形成特定的形状)添加到指定文件中,以备以后使用—如果程序需要,当用户下次画出该手势时,系统可识别该手势。
static GestureLibrary fromFile(String file):从path代表的文件中加载手势库
static GestureLibrary fromFile(File file):从path代表的文件中加载手势库
static GestureLibrary fromPrivateFile(Context context,String name):从指定应用程序的数据文件夹中name文件中加载手势库。
static GestureLibrary fromRawResource(Context context ,int resourceid):
从resourceId所代表的资源中加载手势库。
一旦在程序中获得GestureLibrary对象之后,该对象提供了如下方法来添加手势,识别手势。
Set<String>getGestureEntries():获取该手势库中的所有手势的名称。
ArrayList<Gesture>getGesture(String entryName):获取entryName名称对应的全部手势。
ArrayList<Prediction>getGesture(String entryName):从当前手势库中识别与该gesture匹配的全部手势。
void removeEntry(String entryName):删除手势库中的entryName对应的手势
void removeGesture(String entryName,Gesture gesture):删除手势库中entryName,gesture对应的手势。
boolean save();当向手势库中添加手势或从中删除手势后调用该方法保存手势库。

前面已经提到,GestureLibrary提供了recognize(Gesture ges)方法来识别手势,该方法将会返回该手势库中所有与ges匹配的手势——两个手势的图形越相似,相似度越高。

recognize(Gesture ges)方法返回值为ArrayList<Prediction>,其中Prediction封装了手势的匹配信息,Prediction对象的name属性代表了匹配的手势名,scroe属性代表了手势的相似度。

ContentProvider
可以把ContentProvider当成是安卓系统内部的网站,这个网站以固定的Uri对外提供服务;而ContentProvider则可当成安卓系统内部的HttpClient,它可以向指定Uri发送请求(实际上是调用ContentResolver的方法),这种请求最后委托给ContentProvider处理,从而实现对网站内部数据进行操作。
完整开发一个ContentProvider呢。步骤起始很简单:
1、定义自己的ContentProvider类,该类需要继承安卓提供的ContentProvider基类。
2、向安卓系统注册这个网站,也就是在AndroidMainFest.xml文件中注册这个ContentProvider,就像注册activity一样。注册ContentProvider时需要为它绑定一个URL。
<!-- 下面配置中的name属性指定ContentProvider类 authorities就相当于Contentpriovider指定URL-->
<provider android:name=".dictProvider" android:authorities="org.crazyit.provider.dicitprovider"/>

安卓的Uri与此类似,例如如下Uri:
content://org.crazy.providers.dictprovider/words
它也可以分为三个部分。
content://这个部分是安卓所规定的,是固定的。
org.crazy.providers.dictprovider:这个部分就是Contenprovider的authority。系统就是由这个部分来找到操作哪个contentprovider。只要访问指定的Contentprovider,这个部分总是固定的。
words:资源部分(或者说数据部分),当访问者需要访问不同资源时,这个部分是动态改变的。
需要指出的是,安卓的Uri所能表达的功能更丰富,它还可以支持如下Uri:
content://org.crazy.providers.dictprovider/words/2
此时它要访问你的资源为word/2,这意味着访问word数据中id为2的记录。
为了将一个字符串转换成Uri,安卓提供的Uri工具类提供了parse()静态方法,例如如下代码即可将字符串转换为Uri:
Uri uri =Uri.parse("content://org.crazyit.providers.dictprovider/word/2")

使用ContentResolver操作数据

为了在应用程序中监听ContentProvider数据的改变,需要利用安卓提供ContentObserver基类。
监听ContentProvider数据改变的监听器需要继承ContentObserver类,并重写该基类所定义的onChange(boolean selfChange)方法——当它所监听的ContentProvider的数据发生改变时,该onChange将会触发。

为了监听指定ContentProvider的数据变化,需要通过ContentResolver向指定Uri注册ContentObserver监听器。ContentResolver提供了如下方法来注册监听器:
registerContentObserver(Uri uri ,boolean  notifyForDescendents,ContentObserver observer)
该方法中三个参数的说明如下。
1、uri :该监听器所监听的ContentProvider的Uri.
2、notifyForDescendents :如果该参数为true,假如注册监听的Uri为content://abc,那么Uri为content://abc,那么Uri为content://abc/xyz、content://abc/xyz/foo的数据改变时也会触发该监听器;如果该参数设为false,假如注册监听的Uri为content://abc,那么只有content://abc的数据发生改变时会触发该监听器。
3、observer监听器实例。

ContentProvider的本质就是像一个“小网站”,它可以把应用程序的数据按照“固定规范”暴露出来,其他应用程序就可通过ContentProvider暴露的接口来操作内部的数据了。可以这样说,ContentProvider是安卓系统内不同程序之间进行数据交换的标准接口。ContentResolver用于操作ContentProvider提供的数据,ContentObserver用于监听ContentProvider的数据改变;而ContentProvider则是所有ContentProvider组件的基类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值