欢迎访问 水平网    今天是:2018年01月17日 注册 | 登录 | 订阅 | 收藏
>> 安卓【Android】 >> 编程应用 >> Android开发的一些重要知识2
推荐文章
热点文章

Android开发的一些重要知识2

作者:未知,  来源:网络,  阅读:755,  发布时间:2014-05-19  【放入收藏夹

21. Android Drawable叠加处理方法

大家可能知道Bitmap的叠加处理在Android平台中可以通过Canvas一层一层的画就行了,而Drawable中如何处理呢? 除了使用BitmapDrawable的getBitmap方法将Drawable转换为Bitmap外,今天Android123给大家说下好用简单的LayerDrawable类,LayerDrawable顾名思义就是层图形对象。下面直接用一个简单的代码表示: Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.cwj);
Drawable[] array = new Drawable[3]; array[0] = new PaintDrawable(Color.BLACK); //黑色
array[1] = new PaintDrawable(Color.WHITE); //白色
array[2] = new BitmapDrawable(bm); //位图资源
LayerDrawable ld = new LayerDrawable(array); //参数为上面的Drawable数组
ld.setLayerInset(1, 1, 1, 1, 1); //第一个参数1代表数组的第二个元素,为白色
ld.setLayerInset(2, 2, 2, 2, 2); //第一个参数2代表数组的第三个元素,为位图资源
mImageView.setImageDrawable(ld); 上面的方法中LayerDrawable是关键,Android开发网提示setLayerInset方法原型为public void setLayerInset (int index, int l, int t, int r, int b) 其中第一个参数为层的索引号,后面的四个参数分别为left、top、right和bottom。对于简单的图片合成我们可以将第一和第二层的PaintDrawable换成BitmapDrawable即可实现简单的图片合成。

22. onRetainNonConfigurationInstance和getLastNonConfigurationInstance

很多网友可能知道Android横竖屏切换时会触发onSaveInstanceState,而还原时会产生onRestoreInstanceState,但是Android的Activity类还有一个方法名为onRetainNonConfigurationInstance和getLastNonConfigurationInstance这两个方法。 我们可以通过 onRetainNonConfigurationInstance 代替 onSaveInstanceState,比如距离2 @Override
public Object onRetainNonConfigurationInstance()
{
//这里需要保存的内容,在切换时不是bundle了,我们可以直接通过Object来代替
return obj;
} 在恢复窗口时,我们可以不使用 onRestoreInstanceState,而代替的是 getLastNonConfigurationInstance 方法。我们可以直接在onCreate中使用,比如 Object obj = getLastNonConfigurationInstance(); 最终obj的内容就是上次切换时的内容。 这里Android123提醒大家,每次Activity横竖屏切换时onCreate方法都会被触发。

23. Android中String资源文件的format方法

很多时候我们感性Google在设计Android时遵守了大量MVC架构方式,可以让写公共代码、美工和具体逻辑开发人员独立出来。有关Android的资源文件values/strings.xml中如何实现格式化字符串呢? 这里Android123举个简单的例子,以及最终可能会用到哪些地方。 <?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">cwj_Demo</string>
<string name="hello">android开发网</string>
</resources> 上面是一段简单的字符串资源文件,没有用到格式化,因为比较简单直接描述了意思,当我们设计一个类似 Delete xxx File ? 的时候,我们可能需要在Java中动态获取 xxx 的名称,所以定义资源时使用格式化可以轻松解决,不需要一堆String去拼接或StringBuffer一个一个append这样的愚蠢方法,看例子 <string name="alert">Delete %1$s File</string> 这里%1$s代表这是一个字符串型的,如果是整数型可以写为%1$d,类似printf这样的格式化字符串函数,当然如果包含了多个需要格式化的内容,则第二个可以写为%2$s或%2$d了,那么最终在Java中如何调用呢? 看下面的例子: 例一: 整数型的 <string name="alert">I am %1$d years old</string> 定义的是这样的 当然,我们杜绝意外情况,比如冒出个secret这样的string类型的,注意上面是%1$d不是%1$s,所以默认标准的合并成为 int nAge=23; String sAgeFormat = getResources().getString(R.string.alert); String sFinalAge = String.format(sAgeFormat, nAge); 这样执行完后,就组成了 I am 23 years old,是不是很方便啊. 当然了,下面看下String字符串时的情况. 例二: 字符串型的 String sName="cwj" String sCity="Shanghai" 资源定义为 <string name="alert2">My name is %1$s , I am form %2$s</string> 则Java中只需要 String sInfoFormat = getResources().getString(R.string.alert2); String sFinalInfo=String.format(sInfoFormat, sName, sCity); 我们看到了整个,整个定义类似MFC的CString::Format或Mac OS中的NSLog,但是需要显示类似C#中那样显示的标出参数的数字,比如%1或%n,这里数字代表参数的第n个。本行最终sFinalInfo显示的内容为 My name is cwj , I am form Shanghai 。当然了你有什么不懂的地方可以来函至 android123@163.com

24. Android工程内嵌资源文件的两种方法

Android软件一般处理大的资源通过sdcard比如在线下载资源到sdcard,而apk中内嵌资源或二进制文件时一般使用下面的两种方法: 方法一 res/raw目录下存放,比如cwj.dat一个二进制文件,我们可以读取可以直接 InputStream is=context.getResources().openRawResource(R.raw.cwj); 方法二 工程根目录下的assets文件夹中存放,比如assets/cwj.dat 这样我们使用下面的代码 AssetManager am = context.getAssets();
InputStream is = am.open(cwj.dat); 这里Android123提示大家Google的Android系统处理Assert有个bug,在AssertManager中不能处理单个超过1MB的文件,不然会报异常具体数值大家可以测试下传个稍大的文件,我们在两年前的文章中有提到,而第一种raw没这个限制可以放个4MB的Mp3文件没问题。

25. Android自定义View以及layout属性全攻略

对于Android系统的自定义View可能大家都熟悉了,对于自定义View的属性添加,以及Android的Layout的命名空间问题,很多网友还不是很清楚,今天Android123一起再带大家温习一下 CwjView myView=new CwjView(context); 如果用于游戏或整个窗体的界面,我们可能直接在onCreate中setContentView(myView); 当然如果是控件,我们可能会需要从Layout的xml中声明,比如 <cn.com.android123.CwjView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> 当然,我们也可以直接从父类声明比如 <View class="cn.com.android123.CwjView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> 上面我们仅用了父类View的两个属性,均来自android命名空间,而名称为layout_width或layout_height,我们自定义的控件可能有更多的功能,比如 <cn.com.android123.CwjView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
cwj:age="22"
cwj:university="sjtu"
cwj:city="shanghai"
/> 我们可以看到上面的三个属性,是我们自定义的。作为标准xml规范,可能还包含了类似 xmlns:android="http://schemas.android.com/apk/res/android" 这样的语句,对于定义完整的View,我们的命名空间为cwj,这里可以写为 xmlns:cwj=http://schemas.android.com/apk/res/cn.com.android123.cwjView 或 xmlns:cwj=http://schemas.android.com/apk/res/android 都可以。 对于定义的cwj命名空间和age、university以及city的三个属性我们如何定义呢? 在工程的res/values目录中我们新建一个cwj_attr.xml文件,编码方式为utf-8是一个好习惯,内容如下 <?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="CwjView">
<attr name="age" format="integer" />
<attr name="city" format="string" />
<attr name="university" format="string" />
</declare-styleable>
</resources> 这里我们可能对format不是很熟悉,目前Android系统内置的格式类型有integer比如ProgressBar的进度值,float比如RatingBar的值可能是3.5颗星,boolean比如ToggleButton的是否勾选,string比如TextView的text属性,当然除了我们常见的基础类型外,Android的属性还有特殊的比如color是用于颜色属性的,可以识别为#FF0000等类型,当然还有dimension的尺寸类型,比如23dip,15px,18sp的长度单位,还有一种特殊的为reference,一般用于引用@+id/cwj @drawable/xxx这样的类型。 当然什么时候用reference呢? 我们就以定义一个颜色为例子, <attr name="red" format="color|reference" /> 这里我们用了逻辑或的运算符,定义的红色是颜色类型的,同时可以被引用 当然,对于我们自定义的类中,我们需要使用一个名为obtainStyledAttributes的方法来获取我们的定义。在我们自定义View的构造方法(Context context, AttributeSet attrs)的重载类型中可以用 public CwjView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.cwj_attr);
mAge = a.getInteger(R.styleable.CwjView_age, 22);
mCity = a.getString(R.styleable.CwjView_city, "shanghai");
mUniversity= a.getString(R.styleable.CwjView_university, "sjtu");
a.recycle(); //Android123提示大家不要忘了回收资源 } 这样类的全局成员变量 mAge、mCity就获取了我们需要的内容,当然根据layout中的数值我们自定义的CwjView需要动态的处理一些数据的情况,可以使用AttributeSet类的getAttributeResourceValue方法获取。 public CwjView(Context context, AttributeSet attrs)
{
super(context, attrs);
resId = attrs.getAttributeResourceValue("cn.com.android123.CwjView", "age", 100);
resId = attrs.getAttributeResourceValue("cn.com.android123.CwjView", "city", "shanghai");
//resID就可以任意使用了
} 以上两种方法中,参数的最后一个数值为默认的,如果您有不明白的地方可以来函到 android123@163.com 我们会在第一时间回复。

26. 自定义Android主题风格theme.xml方法

在Android中可以通过自定义主题风格方式来实现个性化以及复用,首先我们创建theme.xml主题文件,保存位置为工程的res/values/theme.xml ,这里我们可以可以为主题起一个名称,比如CWJ,这里去除了xml的文件头<?xml version="1.0" encoding="utf-8"?>这行,我们在工程中只需在androidmanifest.xml文件的Activity节点中加入android:theme="@style/Theme.CWJ" 属性,则这个Activity就使用了这种主题风格,整个xml的关键代码如下: <resources>
<style name="Theme.CWJ" parent="android:Theme">
<item name="android:windowBackground">@drawable/android123</item>
</style>
</resources> 其中上面的代码中,我们定义设置全局android:windowBackground即背景值为/res/drawable中的android123图片为背景,更多的属性定义可以参考view的layout xml属性设置,比如我们设置所有字体颜色、大体大小和样式,可以在style节点中加入 <item name="android:textColor">#fff</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item> 当然我们可以将上面的android123的图片改进下,使用一个xml文件替代,比如使用bitmap对象,则/res/drawable/android123.xml的完整代码变为 <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/cwj_image"
android:tileMode="repeat" /> 这里我们使用了一个bitmap对象来解析cwj_image图片,当然这里可以识别各种类型的图片,其中android:tileMode是bitmap的内部属性,其中tileMode设置为repeat代表重复,这样可以节省bitmap资源,比如我们的背景是一层楼,那么全屏可以显示同样的为5层效果,而图片仅是一层大小,对于资源利用相对更高。 当然bitmap的属性tileMode的值为repeat外还有其他的值比如clamp、mirror,这些值并没有在SDK中并没有找到定义,通过上次Android开发网的 Android自定义View以及layout属性全攻略 一文,我们可以联想到bitmap属于android.graphics.Bitmap 包,由于是android框架,所以下载git的base包,找到该类,类的实例化时android123已经在 Android自定义View以及layout属性全攻略 说的很清楚,所以我们定位到resvalues中找到attr.xml有关bitmap的定义即可,有关bitmap的更多属性如 antialias、filter和dither都可以找到使用。

27. android调试工具monkey压力测试实战

很多Android开发者可能因为没有充分测试自己的软件造成很容易出现FC(Force Close)的问题,这里我们可以通过使用Android固件中自带的monkey工具来做软件的压力测试,monkey工具可以模拟各种按键,触屏,轨迹球、activity等事件,这里Android123提示大家说白了monkey就是一个小猴子随机狂玩你的android软件,看看会不会产生异常。 具体的使用我们通过Android SDK给我们的adb调试桥链接设备或模拟器,进入Linux Shell状态,当然我们可以输入adb shell获取设备的shell,也可以直接通过adb命令执行,比如说adb shell monkey来查看monkey工具中的参数说明,如图: 我们要测试的apk文件要在android设备中已经安装,当然模拟器中也可以测试的。执行adb shell monkey -p cn.com.android123.cwj -v 100 我们执行这句的中包含了p参数,这里代表已安装软件的packageName,而v代表查看monkey生成的详细随机事件名,最后的数字100为我们测试的随机事件数量为100.有关更多的测试方法,请查看上图中的参数,整个测试比较简单单很有效,不妨试试。

28. 自定义View

有关Android的自定义View的框架今天我们一起讨论下,对于常规的游戏,我们在View中需要处理以下几种问题: 1.控制事件 2.刷新View 3. 绘制View 1. 对于控制事件今天我们只处理按键事件onKeyDown,以后的文章中将会讲到屏幕触控的具体处理onTouchEvent以及Sensor重力感应等方法。 2. 刷新view的方法这里主要有invalidate(int l, int t, int r, int b) 刷新局部,四个参数分别为左、上、右、下。整个view刷新 invalidate(),刷新一个矩形区域 invalidate(Rect dirty) ,刷新一个特性Drawable, invalidateDrawable(Drawable drawable) ,执行invalidate类的方法将会设置view为无效,最终导致onDraw方法被重新调用。由于今天的view比较简单,Android123提示大家如果在线程中刷新,除了使用handler方式外,可以在Thread中直接使用postInvalidate方法来实现。 3. 绘制View主要是onDraw()中通过形参canvas来处理,相关的绘制主要有drawRect、drawLine、drawPath等等。view方法内部还重写了很多接口,其回调方法可以帮助我们判断出view的位置和大小,比如onMeasure(int, int) Called to determine the size requirements for this view and all of its children. 、onLayout(boolean, int, int, int, int) Called when this view should assign a size and position to all of its children 和onSizeChanged(int, int, int, int) Called when the size of this view has changed. 具体的作用,大家可以用Logcat获取当view变化时每个形参的变动。 下面cwjView是我们为今后游戏设计的一个简单自定义View框架,我们可以看到在Android平台自定义view还是很简单的,同时Java支持多继承可以帮助我们不断的完善复杂的问题。 public class cwjView extends View { public cwjView(Context context) {
super(context);
setFocusable(true); //允许获得焦点
setFocusableInTouchMode(true); //获取焦点时允许触控
} @Override
protected Parcelable onSaveInstanceState() { //处理窗口保存事件
Parcelable pSaved = super.onSaveInstanceState();
Bundle bundle = new Bundle();
//dosomething
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) { //处理窗口还原事件
Bundle bundle = (Bundle) state; //dosomething
super.onRestoreInstanceState(bundle.getParcelable("cwj"));
return;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) //处理窗口大小变化事件
{
super.onSizeChanged(w, h, oldw, oldh);
} @Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec); //如果不让父类处理记住调用setMeasuredDimension
}
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
super.onLayout (changed,left,top, ight,bottom) ;
} @Override
protected void onDraw(Canvas canvas) {
Paint bg = new Paint();
bg.setColor(Color.Red);
canvas.drawRect(0, 0, getWidth()/2, getHeight()/2, bg); //将view的左上角四分之一填充为红色
} @Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event); //让父类处理屏幕触控事件
} @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { //处理按键事件,响应的轨迹球事件为 public boolean onTrackballEvent (MotionEvent event)
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
break;
case KeyEvent.KEYCODE_DPAD_CENTER: //处理中键按下
break;
default:
return super.onKeyDown(keyCode, event);
}
return true;
} } 上面我们可以看到onMeasure使用的是父类的处理方法,如果我们需要解决自定义View的大小,可以尝试下面的方法 @Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
height = View.MeasureSpec.getSize(heightMeasureSpec);
width = View.MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width,height); //这里面是原始的大小,需要重新计算可以修改本行 //dosomething }

29. Canvas和Paint实例

昨天我们在Android游戏开发之旅三 View详解中提到了onDraw方法,有关详细的实现我们今天主要说下Android的Canvas和Paint对象的使用实例。 Canvas类主要实现了屏幕的绘制过程,其中包含了很多实用的方法,比如绘制一条路径、区域、贴图、画点、画线、渲染文本,下面是Canvas类常用的方法,当然Android开发网提示大家很多方法有不同的重载版本,参数更灵活。 void drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域 void drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象 void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(Android123提示这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。 void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint画刷对象。 void drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。
void drawText(String text, float x, float y, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。 void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) //在路径上绘制文本,相对于上面第二个参数是Path路径对象 从上面来看我们可以看出Canvas绘制类比较简单同时很灵活,实现一般的方法通常没有问题,同时可以叠加的处理设计出一些效果,不过细心的网友可能发现最后一个参数均为Paint对象。如果我们把Canvas当做绘画师来看,那么Paint就是我们绘画的工具,比如画笔、画刷、颜料等等。 Paint类常用方法: void setARGB(int a, int r, int g, int b) 设置Paint对象颜色,参数一为alpha透明通道
void setAlpha(int a) 设置alpha不透明度,范围为0~255 void setAntiAlias(boolean aa) //是否抗锯齿 void setColor(int color) //设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义
.
void setFakeBoldText(boolean fakeBoldText) //设置伪粗体文本
void setLinearText(boolean linearText) //设置线性文本
PathEffect setPathEffect(PathEffect effect) //设置路径效果
Rasterizer setRasterizer(Rasterizer rasterizer) //设置光栅化
Shader setShader(Shader shader) //设置阴影 void setTextAlign(Paint.Align align) //设置文本对齐
void setTextScaleX(float scaleX) //设置文本缩放倍数,1.0f为原始
void setTextSize(float textSize) //设置字体大小
Typeface setTypeface(Typeface typeface) //设置字体,Typeface包含了字体的类型,粗细,还有倾斜、颜色等。 void setUnderlineText(boolean underlineText) //设置下划线
最终Canvas和Paint在onDraw中直接使用 @Override
protected void onDraw(Canvas canvas) { Paint paintRed=new Paint(); paintRed.setColor(Color.Red); canvas.drawPoint(11,3,paintRed); //在坐标11,3上画一个红点
} 下一次Android123将会具体讲到强大的Path路径,和字体Typeface相关的使用。

30. View类详解

在Android游戏开发之旅二中我们讲到了View和SurfaceView的区别,今天Android123从View类开始着重的介绍Android图形显示基类的相关方法和注意点。 自定义View的常用方法: onFinishInflate() 当View中所有的子控件均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发 onSizeChanged(int, int, int, int) 当view的大小发生变化时触发 onDraw(Canvas) view渲染内容的细节 onKeyDown(int, KeyEvent) 有按键按下后触发 onKeyUp(int, KeyEvent) 有按键按下后弹起时触发 onTrackballEvent(MotionEvent) 轨迹球事件 onTouchEvent(MotionEvent) 触屏事件 onFocusChanged(boolean, int, Rect) 当View获取或失去焦点时触发 onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发 onAttachedToWindow() 当view被附着到一个窗口时触发 onDetachedFromWindow() 当view离开附着的窗口时触发,Android123提示该方法和 onAttachedToWindow() 是相反的。 onWindowVisibilityChanged(int) 当窗口中包含的可见的view发生变化时触发 以上是View实现的一些基本接口的回调方法,一般我们需要处理画布的显示时,重写onDraw(Canvas)用的的是最多的: @Override
protected void onDraw(Canvas canvas) {
//这里我们直接使用canvas对象处理当前的画布,比如说使用Paint来选择要填充的颜色 Paint paintBackground = new Paint();
paintBackground.setColor(getResources().getColor(R.color.xxx)); //从Res中找到名为xxx的color颜色定义
canvas.drawRect(0, 0, getWidth(), getHeight(), paintBackground); //设置当前画布的背景颜色为paintBackground中定义的颜色,以0,0作为为起点,以当前画布的宽度和高度为重点即整块画布来填充。 具体的请查看Android123未来讲到的Canvas和Paint,在Canvas中我们可以实现画路径,图形,区域,线。而Paint作为绘画方式的对象可以设置颜色,大小,甚至字体的类型等等。 } 当然还有就是处理窗口还原状态问题(一般用于横竖屏切换),除了在Activity中可以调用外,开发游戏时我们尽量在View中使用类似 @Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Bundle bundle = new Bundle();
bundle.putInt("x", pX);
bundle.putInt("y", pY);
bundle.putParcelable("android123_state", p);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
dosomething(bundle.getInt("x"), bundle.getInt("y")); //获取刚才存储的x和y信息
super.onRestoreInstanceState(bundle.getParcelable("android123_state"));
return;
} 在View中如果需要强制调用绘制方法onDraw,可以使用invalidate()方法,它有很多重载版本,同时在线程中的postInvailidate()方法将在Android游戏开发之旅六中的 自定义View完整篇讲到。

31. View和SurfaceView

在Android游戏当中充当主要的除了控制类外就是显示类,在J2ME中我们用Display和Canvas来实现这些,而Google Android中涉及到显示的为view类,Android游戏开发中比较重要和复杂的就是显示和游戏逻辑的处理。这里我们说下android.view.View和android.view.SurfaceView。SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView,到底有哪些优势呢? SurfaceView可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有Canvas lockCanvas()
Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过下面三个抽象类可以自己定义具体的实现,比如第一个更改格式和显示画面。 abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
abstract void surfaceCreated(SurfaceHolder holder)
abstract void surfaceDestroyed(SurfaceHolder holder)
对于Surface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时Android123未来后面说到的OpenGL中的GLSurfaceView也是从该类实现。

32. Android程序内存管理必读

很多开发者都是从J2ME或J2EE上过来的,对于内存的使用和理解并不是很到位,Android开发网本次给大家一些架构上的指导,防止出现豆腐渣工程的出现。Android作为以Java语言为主的智能平台对于我们开发一些高性能和质量的软件来说了解Android程序内存管理机制是必须的。 Android的Dalvik VM在基础方面和Sun JVM没有什么大的区别仅仅是字节码的优化,我们要知道什么时候用gc什么时候用recycle以及到底用不用finalization,因为Java对内存的分配只需要new开发者不需要显示的释放内存,但是这样造成的内存泄露问题的几率反而更高。 1.对于常规开发者而言需要了解 Java的四种引用方式,比如强引用,软引用,弱引用以及虚引用。一些复杂些的程序在长期运行很可能出现类似OutOfMemoryError的异常。 2.并不要过多的指望gc,不用的对象可以显示的设置为空,比如obj=null,这里Android123提示大家,java的gc使用的是一个有向图,判断一个对象是否有效看的是其他的对象能到达这个对象的顶点,有向图的相对于链表、二叉树来说开销是可想而知。 3.Android为每个程序分配的对内存可以通过Runtime类的totalMemory() freeMemory() 两个方法获取VM的一些内存信息,对于系统heap内存获取,可以通过Dalvik.VMRuntime类的getMinimumHeapSize() 方法获取最小可用堆内存,同时显示释放软引用可以调用该类的gcSoftReferences() 方法,获取更多的运行内存。 4.对于多线程的处理,如果并发的线程很多,同时有频繁的创建和释放,可以通过concurrent类的线程池解决线程创建的效率瓶颈。 5. 不要在循环中创建过多的本地变量。 有关Android和Java的系统性能分析,Android123将在以后的文章中详细讲述如何调试Java分析内存泄露以及Android上的gdb调试器分析得出内存性能改进。

33. Android中内嵌字体实现个性化

在Android中我们的应用可以灵活的内嵌自己的字体文件,实现各个手机上可以正常的显示个性化文字,我们都知道TextView的setTypeface方法可以设置目标文字的显示特性,比如字体、颜色、粗体、斜体等。我们直接找一个TrueTypeFont的字体文件即.ttf,对于Win32系统的用户可以直接在Windows/fonts文件夹中能找到很多。比如微软雅黑就不错,可是体积太大,由于Android的Assets类有单个文件1MB体积的限制,我们先找个英文字体做测试。这里我们将字体文件android123.ttf放到工程的assets文件夹的fonts目录中。 Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/android123.ttf");
TextView tv = (TextView)findViewById(R.id.text); tv.setTypeface(tf); //设置TextView的风格
tv.setText("CWJ Test");
tv.setTextSize(12);
tv.setTextColor(Color.RED);

34. 获取和设置ListView的选择项

获取当前选中项 int curPos = listView.getFirstVisiblePosition(); 当然是用getItemAtPosition(int nPos)方法也可以 ,设置当前选择位置 listView.setSelectedPosition(lastPos); 对于基于AbsListView为基类的ListView等控件均可以使用这种方法。

35. android.text.format文件大小和日期解析类

很多网友可能直接将自己的J2ME项目生硬的移植到Android平台,其实Google为我们提供好了文件大小和时间日期解析类,它位于android.text.format这个包中,它提供了强大的标准化解析方法: 1. IP地址解析类 在android.text.format.Formatter中提供了String formatIpAddress(int addr) 这个方法可以轻松方便的将socket中的int型转成类似127.0.0.1的IP格式,需要注意的是Linux平台的字节顺序,即小字节序、低字节序little-endian。 2. 文件大小解析类 细心的网友可能还看到了android.text.format.Formatter中的formatFileSize方法,该方法String formatFileSize (Context context, long number) ,第二个参数是long型,一般为File对象的最后修改时间或创建时间的方法,最终返回类似 12KB、5Bytes的值,20MB的字符串。 3. 日期时间解析类 ,该类位于android.text.format.DateFormat这个package中,该类提供了Java中的三种时间对象,Android123提示大家下面三种方法为静态可以直接调用,如下: final static CharSequence format(CharSequence inFormat, Date inDate) //传入Date对象
Given a format string and a Date object, returns a CharSequence containing the requested date. final static CharSequence format(CharSequence inFormat, Calendar inDate) //Calendar对象
Given a format string and a Calendar object, returns a CharSequence containing the requested date. final static CharSequence format(CharSequence inFormat, long inTimeInMillis) //long对象
Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a CharSequence containing the requested date. 我们可能看到了第一个参数均为inFormat这是一个CharSequence接口的String类型,它提供了灵活的时间格式解析字符串描述,Android开发网提示大家注意大小写要区分,如 April 6, 1970 at 3:23am 例子,那么inFormat参数的写法和最终执行的结果如下对照,下面就以Android123的CWJ生日为例子如下 "MM/dd/yy h:mmaa" -> "11/03/87 11:23am"
"MMM dd, yyyy h:mmaa" -> "Nov 3, 1987 11:23am"
"MMMM dd, yyyy h:mmaa" -> "November 3, 1987 11:23am"
"E, MMMM dd, yyyy h:mmaa" -> "Tues, November 3, 1987 11:23am"
"EEEE, MMMM dd, yyyy h:mmaa" -> "Tuesday, Nov 3, 1987 11:23am" 对于判断一个时间是否为24小时制式可以通过android.text.format.DateFormat类的static boolean is24HourFormat(Context context)方法来判断。

36. Android代码性能优化技巧

目前来说Android 2.2的JIT性能有了本质的提高,不过对于老版本的程序提高Java执行效率还有很多语言特点来说,今天Android123提到的不是语法糖,而是基础的问题,对于Java 1.5之后将会有明显的改进。下面的例子来自SDK: static class Foo {
int mSplat;
}
Foo[] mArray = ... 上面的静态类Foo的执行效果和性能,我们分三个方法zero、one和two来做对比。
public void zero() { //大多数人可能简单直接这样写
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray.mSplat;
}
}
public void one() { //通过本地对象改进性能
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray.mSplat;
}
}
public void two() { //推荐的方法,通过Java 1.5的新语法特性可以大幅改进性能
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
} zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop. one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit. two() is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.

37. Android开发注意点 Part One

Android已经的很多细节问题我们通过平台开发总结不断完善这个列表,如果你有相关的内容可以联系 android123@163.com . 一、AssetManager - 已知单个文件处理不能大于1MB,所以如果资源很大,建议使用Zip格式压缩存放。 二、ScrollView中嵌入ListView - 这个作法可能会出现你的ListView仅仅显示1行半。 三、Android自带的Zip处理类对文件名编码无法识别,也没有提供显示的设置方法,在zlib中写死了。 四、使用一些资源对象记住关闭,比如对于文件流对象最后 FileOutputStream os = xxx; try {
//dosomething
} finally {
os.close(); //显示的使用finally关闭文件对象。
} 对于Cursor而言,在移动位置时首先判断Cursor是否为空,最终使用完仍然需要 close方法,如果重用,可以使用deactivate方法释放当前资源,通过requery方法再次查询。 五、SDK中标记为 deprecated 字样的,常规情况下是有更好的方法可以替代,短期内可以放心使用。这些方法一般高版本的SDK都可以向上兼容,目前尚未发现Android放弃某些API的支持。 六、Notification的Intent无法传递到目标的Activity,Service和Broardcast没有测试过,中途需要通过PendingIntent,可能这里出现了问题。

38. Android上HTTP协议通讯状态获取

通常情况下轻量级的Http传输Android平台可以直接使用Sun Java的HttpURLConnection类方法处理,比如果自己定义一次请求header可以通过setRequestProperty设置,而我们需要获取的Http Web Server状态可以通过HttpURLConnection.getResponseCode() 的方法获取。 当然Http协议返回值常见的有 200 为成功,400为请求错误,404为未找到,500为服务器内部错误,403无权查看,302为重定向等等。 对于Android平台提供更完善的Apache类有HttpClient 、HttpPost、HttpResponse、HttpGet和HttpEntity,其中对于数据报头header构造通过HttpEntity,而返回状态值可以通过HttpResponse获取。 有关Android客户端和Server通讯类相关的开发我们将会在以后文章中做大量实例介绍。

39. Android布局Java代码构造法

一般情况下对于Android程序布局我们往往使用XML文件来编写,这样可以提高开发效率,但是考虑到代码的安全性以及执行效率,可以通过Java代码执行创建,虽然Android编译过的xml是二进制的,但是加载xml解析器的效率对于资源占用还是比较大的,一般一个简单的TextView,比如 <TextView
android:id="@+id/textControl "
android:layout_width="100px"
android:layout_height="wrap_content" /> 可以等价于下面的Java代码: LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(100, LayoutParams.WRAP_CONTENT); //宽度为100px,高为自适应最小的高度 // setOrientation(VERTICAL); 设置布局为垂直 TextView textControl = new TextView(this);//如果从一个XXXLayout.,比如LinearLayout为View的基类时这里this应该换成为创建改类的Context
textControl.setText("Android开发网欢迎您");
addView( textControl, textParams ); 当然Java处理效率比XML快得多,但是对于一个复杂界面的编写,可能需要一些套嵌考虑,如果你思维灵活的话,使用Java代码来布局你的Android应用程序是一个更好的方法。

40. 测试Android软件性能主要方法

对于Android平台上软件的性能测试可以通过以下几种方法来分析效率瓶颈,目前Google在Android软件开发过程中已经引入了多种测试工具包,比如Unit测试工程,调试类,还有模拟器的Dev Tools都可以直接反应执行性能。 1. 在模拟器上的Dev Tools可以激活屏幕显示当前的FPS,CPU使用率,可以帮助我们测试一些3D图形界面的性能。 2. 一般涉及到网络应用的程序,在效率上和网速有很多关系,这里需要多次的调试才能实际了解。 3. 对于逻辑算法的效率执行,我们使用Android上最普遍的,计算执行时间来查看: long start = System.currentTimeMillis();
//android开发网提示这里做实际的处理do something
long duration = System.currentTimeMillis() - start; 最终duration保存着实际处理该方法需要的毫秒数。这里类似Win32上的GetTickCount,在Win 32和Symbian上都提供了高精度的性能计数器和低阶计时器,这里在Dalvik VM上的Java层这种方法对于一般的应用足以。 4. GC效率跟踪,如果你执行的应用比较简单,可以在DDMS中查看下Logcat的VM释放内存情况,大概模拟下那些地方可以缓存数据或改进算法的。 5. 线程的使用和同步,Android平台上给我们提供了丰富的多任务同步方法,但在深层上并没有过多的比如自旋锁等高级应用,不过对于Service和appWidget而言,他们实际的产品中都应该以多线程的方式处理,以释放CPU时间,对于线程和堆内存的查看这些都可以在DDMS中看到。 更多的调试和性能测试方法Android123将在以后的内容中出现。
TGAS:Android
评论【共有0条评论】查看所有评论
昵称:(*)   邮箱:   QQ:   验证码: 看不清楚?点击刷新验证码