zoukankan      html  css  js  c++  java
  • 性能调优UI篇(一)——ViewStub

    在项目中,我们忙于赶着功能的实现,整个app的性能很差。每个页面加载都卡到不行。暑假马上就要到了,项目组专门安排了一个提升性能的版本。版本还没开始做,我提前在这里记录一下性能调优的一些方法和尝试。

    今天学习并尝试的是ViewStub。在app的UI中,我们时常会有一些View是“隐形的”即,我会在xml中给它设置将它的visibility设为gone。只有在特殊情况下,我才会将它显现出来。比如悬浮的Button会在我滑动内容时消失,部分按钮只有有权限的用户才看见等等情况。用View设置visibility的方式,最大的好处就是灵活。我可以动态地在程序中,根据一些条件判断,随时显现或者隐藏这些控件,使整个交互充满灵动。

    但除了以上情况,还有另一种情况。比如,在列表为空时,我会加载一幅特殊的画,用以提示用户列表没有内容,或者在用户第一次登录时会显示每个按钮,之后就不会再看到了。这些情况归纳起来就是,这些控件大部分情况下处于隐形状态。只有少数情况它需要被显示出来。我如果依然把它写在xml里面,只是设置一下visibility = gone,显得非常不划算。因为不论visibility设置成什么,系统都已经把它加载出来了,加载的时间已经花了,内存也占用了,我却有很大的可能根本不会使用它。因此,我们可以使用ViewStub。ViewStub是一个轻量级的view,我们只有一次给它绘制的机会。它在不绘制时,占用的内存是非常小的,且加载时间也很短。当我们需要它时,我们再绘制它,整体花的时间与View的直接加载相差不大。所以,如果这个View显示的机会不多,我们更推荐使用ViewStub进行显示。

    代码如下:

    activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">
    
            <Button
                android:id="@+id/test_btn2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_centerInParent="true"
                android:text="test2"
                android:onClick="testclick2"/>
            <ViewStub
                android:id="@+id/test_view2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:inflatedId="@+id/test_image_view"
                android:layout_above="@id/test_btn2"
                android:layout="@layout/test_image_view"
                />
        </RelativeLayout>
    </LinearLayout>

    test_image_view.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/test_img_src"
            />
    
    </LinearLayout>

    MainActivity.java:

    package com.dream.fishbonelsy.viewstubdemo;
    
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewStub;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    
    public class MainActivity extends ActionBarActivity {
    private ViewStub view2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            long startTime = System.nanoTime();  //开始时间        super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            view2 = (ViewStub) findViewById(R.id.test_view2);
            long consumingTime = System.nanoTime() - startTime; //消耗时间
            Log.d("tag" , "布局时间:"+ consumingTime/1000000+"毫秒");
        }
    
        public void testclick2(View view){
            long startTime = System.nanoTime();  //开始时间
            view2.inflate();
            long consumingTime = System.nanoTime() - startTime; //消耗时间
            Log.d("tag" , "绘制时间:"+consumingTime/1000000+"毫秒");
        }
    }

     消耗时间如图:

    相同的内容我经过了多次测试,发现ViewStub的布局时间非常短,之后加载也不会太慢。对于同样的内容,我采用了ImageView设置visibility尝试了一次。

    代码如下:

    activity_main.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">
    
            <Button
                android:id="@+id/test_btn1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_centerInParent="true"
                android:text="test1"
                android:onClick="testclick1"/>
            <ImageView
                android:id="@+id/test_view1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/test_img_src"
                android:visibility="gone"
                android:layout_above="@id/test_btn1"
                />
        </RelativeLayout>
    </LinearLayout>

    MainActivity.java:

    package com.dream.fishbonelsy.viewstubdemo;
    
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewStub;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    
    public class MainActivity extends ActionBarActivity {
    
        private ImageView view1;
        private ViewStub view2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            long startTime = System.nanoTime();  //開始時間
    //
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            view1 = (ImageView) findViewById(R.id.test_view1);
            //view2 = (ViewStub) findViewById(R.id.test_view2);
            long consumingTime = System.nanoTime() - startTime; //消耗時間
            Log.d("tag" , "布局时间:"+ consumingTime/1000000+"毫秒");
        }
    
        public void testclick1(View view){
            long startTime = System.nanoTime();  //開始時間
            view1.setVisibility(View.VISIBLE);
    
            long consumingTime = System.nanoTime() - startTime; //消耗時間
            Log.d("tag", "绘制时间:" + consumingTime / 1000 + "微秒");
        }
    }

    消耗时间如图:

    分析上面两份时间数据我们可以观察出这样的结果:

    一、两种方案在要显示这个图时,所花的时间是相当的。此时用View更好,因为View更灵活,我可以反反复复地隐藏和显现,可以设置点击事件,甚至可以重绘等等。

    二、两种方案在不显示这张图时,ViewStub的加载时间会大大降低,同样的,消耗内存也会少很多。

    因此,可以暂时总结为:当我需要一个灵活的控件,它需要变化、监听、隐藏、移动时,我应该选择View。由于,ViewStub只能绘制一次,不能监听,不能重绘,不能移动,不能隐藏,所以当我需要一个不常显示的备用View时,使用ViewStub可以大大节省我们的系统资源。(比如,当列表内容为空,显示某图;当网络情况不好,显示某图;当用户第一次登录,显示某图)。我们需要预估这个View出现的频率,来最终决定方案。

    暂时Done。

    发现性能优化真是需要丰富的经验,然后一点点扣出来的性能。学海无涯啊~

  • 相关阅读:
    sqlhelper使用指南
    大三学长带我学习JAVA。作业1. 第1讲.Java.SE入门、JDK的下载与安装、第一个Java程序、Java程序的编译与执行 大三学长带我学习JAVA。作业1.
    pku1201 Intervals
    hdu 1364 king
    pku 3268 Silver Cow Party
    pku 3169 Layout
    hdu 2680 Choose the best route
    hdu 2983
    pku 1716 Integer Intervals
    pku 2387 Til the Cows Come Home
  • 原文地址:https://www.cnblogs.com/fishbone-lsy/p/4565026.html
Copyright © 2011-2022 走看看