android 客户端开发中,很多ui细节要处理,这里就总结下工作中用到的和会用到的ui 方法的优化知识:

一,布局优化:

public_layout.xml



1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical"
 4     android:layout_width="fill_parent"
 5     android:layout_height="fill_parent"
 6     >
 7 <TextView  
 8     android:layout_width="fill_parent" 
 9     android:layout_height="wrap_content" 
10     android:text="public_view"
11     />
12 </LinearLayout>



 

  1. <include/> 标签的使用:很容易就能做到共享和重用布局,方便管理页面公用的布局,类似topBar,bottomBar
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3     android:orientation="vertical"
4     android:layout_width="fill_parent"
5     android:layout_height="fill_parent">
6     <include android:id="@+id/new" layout="@layout/public_layout"></include>
7 </LinearLayout>
  1. <merge/>标签的使用:一般情况下能够帮我们减少一个布局层次,用法有点复杂,提升不大,不建议使用~;
1 <?xml version="1.0" encoding="utf-8"?>
2 <merge xmlns:android="http://schemas.android.com/apk/res/android"
3    <include android:id="@+id/newone" layout="@layout/public_layout"></include>
4 <include android:id="@+id/newtwo" layout="@layout/public_layout"></include>
5 </merge>
  1. <Viewstub/>标签的使用:很多情况下,一个布局中有很多View并不常用,这就造成了资源的浪费,android为此提供了ViewStub标签来解决这个问题。在默认情况下ViewStub下的标签都有visibility=GONE属性(不可见),更重要的是在这个标签下的内容不会占用任何的空间。其实ViewStub和include类似,不过区别就在于ViewStub只会在你需要的时候进入你的界面,viewStub通过inflate()方法来通知系统加载其内部的View。这样就可以让我们既享受到<include/>的便利,又不会产生过多没用的View。main.xml:
1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical"
 4     android:layout_width="fill_parent"
 5     android:layout_height="fill_parent"
 6     >
 7 <Button
 8     android:id="@+id/show"
 9     android:layout_width="wrap_content"
10     android:layout_height="wrap_content"
11     android:text="点击导入"
12     />
13 <ViewStub  
14     android:id="@+id/viewStub"  
15     android:layout="@layout/public_layout"  
16     android:layout_width="wrap_content"  
17     android:layout_height="wrap_content"  
18     /> 
19 </LinearLayout>

在代码中应用:

ViewStub stub = (ViewStub) findViewById(R.id.stub);
View inflated = stub.inflate();

ViewStub的一些特点:

         1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。

         2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。

     基于以上的特点,那么可以考虑使用ViewStub的情况有:

         1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。

              因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。

         2. 想要控制显示与隐藏的是一个布局文件,而非某个View。

              因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。

     所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。

  1. 使用sdk自带的 Hierarchy Viewer工具,这是一个非常好的布局优化工具,同时,你也可以通过它学习他人的布局。详细方法可以参考:
  2. layoutopt 工具,也不错 ,只是ADT 16之前的sdk 才能使用,后被google放弃了;
  3. Lint的使用,这是一个很不错的,很强大的UI帮助工具;每个错误都有详细的解释,可以直接定位到源码链接,错误行,直接提供修改的意见,可以生成html 文档
  4. 减少不必要的View以及View的嵌套层次。比如实现一个listview中常用的layout,可以使用RelativeLayout减少嵌套,要知道每个View的对象会耗费1~2k内      存,嵌套层次过多会引起频繁的gc,造成ANR。
  5. Drawing and Invalidating : 在Android开发过程中,每个View的内容并非都是一成不变的。在变更View的内容后,我们需要进行刷新使得屏幕上的内容与之一致。
    一般来说这个操作直接调用View.invalidate()刷新整个View即可。然而很多情况下,内容变更的区域并不是整个View,而只是其中的一部分。这时如果仍然直接调用View.invalidate()的话代价就显得有些高昂,一种推荐的方法是改为调用View.invalidate(Rect)或者View.invalidate(left, top, right, bottom)刷新View的指定区域。

  10,Background and Images :我们可以对任何View设置背景图像Background drawable,应用程序在显示View时会自动进行拉伸、缩放(Auto-scale)使图像能够完全填充View的显示区域,而在运行时拉伸/缩放图像显然会降低程序运行效率(计算成本高,容易引发Out of Memory)。

// Rescales originalImage to the size of view using
// bitmap filtering for better results
originalImage =Bitmap.createScaledBitmap( originalImage,// bitmap to resize
 view.getWidth(),// new width
 view.getHeight(),// new height
true);// bilinear filtering

  11,通过theme 预加载背景 或者窗口不需要背景的时候设置@null

 


1 <!-- res/values/styles.xml -->
2 <resources>
3     <style name="Theme.NoBackground" parent="android:Theme">
4         <item name="android:windowBackground">@null</item>
5     </style>
6 </resources>



在activity中设置



1 <activity
2     android:name="MyApplication"
3     android:theme="@style/NoBackgroundTheme">
4     <!-- intent filters and stuff -->
5 </activity>



 

二,adapter优化:

adapter 是数据与view之间的桥梁,类似listview 中使用baseAdapter ,getView()方法的优化是关键

比较成熟的优化方案:



1 static class ViewHolder
 2     {
 3         TextView text;
 4         ImageView icon;
 5     }
 6     
 7     public View getView( int position, View convertView, ViewGroup parent )
 8     {
 9         ViewHolder holder;
10 
11         if ( convertView == null )
12         {
13             convertView = mInflater
14                     .inflate( R.layout.list_item_icon_text, null );
15 
16             holder = new ViewHolder( );
17             holder.text = ( TextView ) convertView.findViewById( R.id.text );
18             holder.icon = ( ImageView ) convertView.findViewById( R.id.icon );
19 
20             convertView.setTag( holder );
21         }
22         else
23         {
24             holder = ( ViewHolder ) convertView.getTag( );
25         }
26 
27         holder.text.setText( DATA[ position ] );
28         holder.icon.setImageBitmap( ( position & 1 ) == 1 ? mIcon1 : mIcon2 );
29 
30         return convertView;
31     }



如果对性能要求比较高可以 硬编码 布局,不使用耗时的xml,xml加载解析为java代码是耗时的,findviewByid 也是耗时的;

总结:1,重用convertView;2,较少查询次数 findviewbyid;3,分段加载listview (分页);4,布局硬编码