setOrientation(VERTICAL); 设置布局为垂直 TextView textControl = new TextView(this);//如果从一个XXXLayout.,比如LinearLayout为View的基类时这里this应该换成为创建改类的Context
textControl.setText(\开发网欢迎您\
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将在以后的内容中出现。 41. Splash Screen开场屏在Android中的实现
很多网友可能发现近期Tencent推出的手机QQ Android版包含了一个开场屏Splash Screen载入效果,通常游戏或大型软件打开时可能需要一个释放解析资源的过程,需要一个前台的动画播放和后台的逻辑处理线程配合,当然对于简单的软件也可以加一个Splash Screen作为美化。在Android平台上如何实现呢? 首先创建一个Activirty,在SetContentView时直接通过ImageView创建一个全屏的图片,Android123提示大家还要考虑好分辨率和当前设备一致,onCreate添加代码如下: new Handler().postDelayed(new Runnable(){ // 为了减少代码使用匿名Handler创建一个延时的调用
public void run() {
Intent i = new Intent(SplashScreen.this, Main.class); //通过Intent打开最终真正的主界面Main这个Activity
SplashScreen.this.startActivity(i); //启动Main界面 SplashScreen.this.finish(); //关闭自己这个开场屏 }
}, 5000); //5秒,够用了吧 42. Android的Activity你知多少呢?
看到这个标题很多网友肯定回答,我知道Activity是Android上的窗口基类,了解Activity的生命周期比如onCreate onStop等,呵呵,按照这样说Android123还知道Activity的实现其实是从ApplicationContext,而ApplicationContext是从Context这个抽象类派生而来的,当然我们看到显示的是View或者ViewGroup,当然今天说的不是这些东西,而是很多网友来问的Android为什么不设计一个任务管理器,当然从Android 1.5开始ActivityManager类提供了restartPackage可以关闭一个程序,需要加上 cwj.class); i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); //Android开发网提示大家相关的还有Intent.FLAG_ACTIVITY_CLEAR_TOP,都试试 startActivity(i); 当然更多的程序Activity控制可以再androidmanifest.xml中定义。 43. JSONObject在Android上的应用 如果你过去开发过AJAX应用,相信对JSONObject不会陌生吧,作为基于JavaScript的数据交换格式,可以直接代替Xml,这里Android从1.0开始就完全支持JSONObject。在平时应用中直接引入import org.json.JSONObject;即可方便使用。当然同类的还有SOAP。 在常规使用方便JSONObject对象可以实现类似Bundle或Parcel可以封装数据,代替一个XML的ITEM,但最大的优势是可以执行一些简单的方法,比如说getString、has、put、getBoolean、getInt等数据类型的存取操作。Android123提示大家对于常规的项目开发,今天本文不考虑Server端的布局,在Android平台上处理这些比较简单,主要是一些http的请求处理。可以直接引入import org.apache.http.xxx来实现web server层的数据交换,如果你没有专业的Server开发技术,可以通过简单的Web配合JSON方式快速实现自己的交互式应用。 44. Android高性能文件类MemoryFile 很多网友抱怨Android处理底层I/O性能不是很理想,如果不想使用NDK则可以通过MemoryFile类实现高性能的文件读写操作。MemoryFile顾名思义就是内存文件的意思,如果你过去从事过Win32开发,那么它的原理就是MapViewOfFile(),当然开发过Linux的网友可能很快就联想到了mmap(),是的该类就是他们的托管代码层封装,位于android.os.MemoryFile这个位置,从Android 1.0开始就被支持。 MemoryFile适用于哪些地方呢? 对于I/O需要频繁操作的,主要是和外部存储相关的I/O操作,MemoryFile通过将 NAND或SD卡上的文件,分段映射到内存中进行修改处理,这样就用高速的RAM代替了ROM或SD卡,性能自然提高不少,对于Android手机而言同时还减少了电量消耗。Android123提示网友该类实现的功能不是很多,直接从Object上继承,通过JNI的方式直接在C底层执行。 主要的构造方法 MemoryFile(String name, int length) ,这里第二个参数为文件大小,需要说明的是Android的MemoryFile和传统的mmap还有一点点区别,毕竟是手机,它内部的内存管理方式ashmem会从内核中回收资源。毕竟目前部分低端机型的RAM也比较吃紧。 synchronized boolean allowPurging(boolean allowPurging) //允许ashmem清理内存,线程安全同步的方式。 void close() //关闭,因为在Linux内部mmap占用一个句柄,不用时一定要释放了 InputStream getInputStream() 返回读取的内容用Java层的InputStream保存 OutputStream getOutputStream() 把一个OutputSream写入到MemoryFile中 boolean isPurgingAllowed() //判断是否允许清理 int length() //返回内存映射文件大小 下面就是我们熟悉的,读写细节,主要是对字符数组的操作,这里大家要计算好每个文件类型的占用,同时考虑到效率对于自己分配的大小考虑粒度对齐。 int readBytes(byte[] buffer, int srcOffset, int destOffset, int count) void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count) 具体的实际应用,Android开发网将在下次和大家讲到。 45. TextUtils类-Android字符串处理类 对于字符串处理Android为我们提供了一个简单实用的TextUtils类,如果处理比较简单的内容不用去思考正则表达式不妨试试这个在android.text.TextUtils的类,主要的功能如下: 是否为空字符 static boolean isEmpty(CharSequence str) 拆分字符串 public static String[] split (String text, String expression) ,Android开发网提示大家仔细看例子如下 String.split() returns [''] when the string to be split is empty. This returns []. This does not remove any empty strings from the result. For example split(\拆分字符串使用正则 public static String[] split (String text, Pattern pattern) 确定大小写是否有效在当前位置的文本TextUtils.getCapsMode(CharSequence cs, int off, int reqModes) 使用HTML编码这个字符串 static String TextUtils.htmlEncode(String s) 46. InputSream输入流转String字符串,Android开发工具类 在Android平台上使用Java层处理I/O时主要使用流,这里Android开发网给大家一个方便的类,可以处理InputStream输入流转为String字符串,在效率上,我们使用了字符串拼接StringBuilder类减少内存碎片以及BefferedReader类实现一个缓存。 private String Stream2String(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is), 16*1024); //强制缓存大小为16KB,一般Java类默认为8KB StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { //处理换行符 sb.append(line + \ } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } } 47. layout资源包含,android开发必读 有时候我们在一个Android程序中可能会复用布局文件,这时可以在一个xml文件中复用过去的布局文件,但是和常规的使用不同的是,需要加上类似包含头文件一样的include关键字,比如下面我们需要包含layout文件夹下的view.xml布局文件,需要 encoding=\ android:orientation=\ android:layout_width=\ android:layout_height=\ > android:layout_width=\ android:layout_height=\ android:text=\ /> 48.Android控件开发之ToggleButton原理 在Android平台上比较有特色的就是ToggleButton控件,虽然它的功能和CheckBox有些类似,但是他们的用处还是有一定的区别比如ToggleButton原本有图片装饰,通过ToggleButton可以很清楚的显示某些状态。它们均从Button为基类的CompoundButton中实现,其真假事件从Checkable来实现。 public abstract class CompoundButton extends Button implements Checkable { private boolean mChecked; //状态是否选中 private int mButtonResource; private boolean mBroadcasting; private Drawable mButtonDrawable; //按钮的图标 private OnCheckedChangeListener mOnCheckedChangeListener; //选中状态改变监听 private OnCheckedChangeListener mOnCheckedChangeWidgetListener; private static final int[] CHECKED_STATE_SET = { R.attr.state_checked }; public CompoundButton(Context context) { this(context, null); } public CompoundButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CompoundButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0); Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); if (d != null) { setButtonDrawable(d); } boolean checked = a .getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false); setChecked(checked); a.recycle(); //显式的GC } public void toggle() { setChecked(!mChecked); } @Override public boolean performClick() { toggle(); return super.performClick(); } public boolean isChecked() { return mChecked; } public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); //更新当前状态的按钮图标 if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); } mBroadcasting = false; } } public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) { mOnCheckedChangeWidgetListener = listener; } public static interface OnCheckedChangeListener { void onCheckedChanged(CompoundButton buttonView, boolean isChecked); } public void setButtonDrawable(int resid) { if (resid != 0 && resid == mButtonResource) { return; } mButtonResource = resid; Drawable d = null; if (mButtonResource != 0) { d = getResources().getDrawable(mButtonResource); } setButtonDrawable(d); } public void setButtonDrawable(Drawable d) { if (d != null) { if (mButtonDrawable != null) { mButtonDrawable.setCallback(null); unscheduleDrawable(mButtonDrawable); } d.setCallback(this);