美文网首页
Android 性能优化--UI

Android 性能优化--UI

作者: Mr_不靠谱_先森 | 来源:发表于2017-07-24 17:31 被阅读27次

    布局标签

    • include
      <include>
      的用途就是将布局中的公共部分提取出来以供其他Layout使用,从而实现布局的优化。这种布局的编写方式大大便利了开发,个人感觉这种思想和React Native中的面向组件编程思想有着异曲同工之妙,都是将特定功能抽取成为一个独立的组件,只要控制其中传入的参数就可以满局不同的需求。例如:我们在编辑Android界面的时候常常需要添加标题栏,如果在不使用<include>
      的情况下,只能在每一个需要显示标题栏的xml文件中编写重复的代码,费时费力。但是只要我们将这个需要多次被使用的标题栏布局抽取成一个独立的xml文件,然后在需要的地方使用<include>
      标签引入即可。
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@+id/simple_list_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="80dp" />
    
        <include
            android:id="@+id/my_foot_ly"
            layout="@layout/foot" />
    
    </RelativeLayout>
    

    其中include引入的foot.xml为公用的页面底部,代码如下:

    ?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:id="@+id/my_foot_parent_id">
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_above="@+id/title_tv"/>
    
        <TextView
            android:id="@+id/title_tv"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_alignParentBottom="true"
            android:text="@string/app_name" />
    </RelativeLayout>
    

    注意
    在使用<include>标签最常见的问题就是 findViewById查找不到<include>进来地控件的跟布局,而这个问题出现的前提就是在include的时候设置了id。当设置id后,原有的foot.xml跟布局Id已经被替换为在 <include>中指定的id了,所以在 findViewById查找原有id的时候就会报空指针异常。

    <include>标签简单的说就是相当与将layout指定的布局整体引入到main.xml中。所以我们就和操作直接在main.xml中的布局是一样的只不过有一个上面提到的更布局id被覆盖的问题。

    • ViewStub

    ViewStub标签同include一样可以用来引入一个外部布局。不同的是,ViewStub引入的布局默认是不会显示也不会占用位置的,从而在解析的layout的时候可以节省cpu、内存等硬件资源。

    ViewStub常常用来引入那些默认不显示,只在特定情况下才出现的布局,例如:进度条,网络连接失败显示的提示布局等

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
    ……
        <ViewStub
            android:id="@+id/network_error_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout="@layout/network_error" />
    
    </RelativeLayout>
    

    其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <Button
            android:id="@+id/network_setting"
            android:layout_width="@dimen/dp_160"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:text="@string/network_setting" />
    
        <Button
            android:id="@+id/network_refresh"
            android:layout_width="@dimen/dp_160"
            android:layout_height="wrap_content"
            android:layout_below="@+id/network_setting"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/dp_10"
            android:text="@string/network_refresh" />
    
    </RelativeLayout>
    

    在代码中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:

    private View networkErrorView;
    
    private void showNetError() {
      if (networkErrorView != null) {
        networkErrorView.setVisibility(View.VISIBLE);
      }else{
        ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
        if(stub !=null){
          networkErrorView = stub.inflate();
    
          //  效果和上面是一样的
          //  stub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
          //  networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局
        }
     }
    }
    
    private void showNormal() {
      if (networkErrorView != null) {
        networkErrorView.setVisibility(View.GONE);
      }
    }
    

    在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。

    • merge

    在使用了include后可能会导致布局嵌套太多,导致视图节点太多,减慢了解析速度。

    merge标签可用于两种典型情况:

    1. 布局顶接点是FrameLayout并且不需要设置background或者padding等属性,可使用merge代替,因为Activity内容视图的parent view就是一个FrameLayout,所以可以用merge消除只能一个。
    2. 某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时,顶结点会自动被忽略,而其自己点全部合并到主布局中。
      以include引入的foot.xml为公用的页面底部 为例
      可以发现多了一层没必要的RelativeLayout,将foot.xml中RelativeLayout改为merge,如下:
    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_above="@+id/text"/>
    
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_alignParentBottom="true"
            android:text="@string/app_name" />
    
    </merge>
    

    绘制优化

    绘制优化是指View的onDraw方法要避免执行大量的操作

    相关文章

      网友评论

          本文标题:Android 性能优化--UI

          本文链接:https://www.haomeiwen.com/subject/qfbbkxtx.html