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。

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

  • 相关阅读:
    Mongoexport导出数据,Mongoimport导入数据,mongodump备份数据,mongorestore恢复恢复
    php7中使用mongodb的驱动
    windows(X64)+apche2.4+php7.2下安装mongodb
    windows(X64)下安装apche2.4+php7.2+mysql5.7
    Django2.0 path与Django1.x版本url正则匹配问题
    Django: ImportError: No module named 'corsheaders'
    linux开启端口
    MySQL 存储过程传参数实现where id in(1,2,3,...)示例
    ubuntu安装pip3
    在Ubuntu 16.04 安装python3.6 环境并设置为默认
  • 原文地址:https://www.cnblogs.com/fishbone-lsy/p/4565026.html
Copyright © 2011-2022 走看看