• Google I/O 大会上提出的UI优化相关


    1、ListView的Adapter

        Adapter在ListView中的工作原理是:

        

    上图也正好反映出ListView使用了Adapter来适配数据源。

    每一个Item条目都是通过Adapter.getView得到的。每次假如不处理会返回一个新的view,这是非常耗费性能的。

    要这样做:

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

    这样性能会大幅的提升。

    二、图片和Activity的背景

     背景图片总是会拉伸来适应view,但是正在运行的拉伸是很耗性能的。应该做一下图像的预处理

    // 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); // bil

    而Activity的背景有时是没有必要的,而它们默认都是填充屏幕,这是耗性能的。可以考虑去掉背景:

    Removing the background
    20
    <!-- res/values/styles.xml -->
    <resources>
    <style name="Theme.NoBackground" parent="android:Theme">
    <item name="android:windowBackground">@null</item>
    </style>
    </resources>
    
    <activity
     android:name="MyApplication"
     android:theme="@style/NoBackgroundTheme">
    <!-- intent filters and stuff -->
    </activity>

    三、Drawing and invalidating

     虽然平时我们都用invalidate(),因为不需要任何参数,很简单。但是性能并不高。

     应该

    –invalidate(Rect)
    –invalidate(left, top, right, bottom)

    效率比不传参数高一些。因为这是局部去刷新。

    四、view和布局文件

    原则是布局越简单、层级越少,性能会越好。因为系统在加载view的时候就能花更少的时间去计算位置、去绘画它们。

    可以有一些优化的方面:

    1、Textview可以设置一个drawable来替代

    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content">
    <ImageView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:src="@drawable/icon" />
    <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/hello" />
    </LinearLayout>

    仅仅需要一个TextView就可以搞定

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:drawableLeft="@drawable/icon" />

    2、使用ViewStub

    在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。

          推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。

    但是它也有不足的地方:

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

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

    因此使用的时候还是要注意的。要根据实际需求来决定

    3、<merge />

    当最外层的节点是FrameLayout时,因为所有的Activity view 的父节点都是FrameLayout,因此这会出现两个FrameLayout,用merge,系统在解析xml时会忽略merge,并把它的子节点添加到merge的父节点上,这样就节省了一个层级。提高了Layout的性能。

    <merge />标签极其有用。然而它也有以下两个限制:

    • <merge />只能作为XML布局的根标签使用
    • 当Inflate以<merge />开头的布局文件时,必须指定一个父ViewGroup,并且必须设定attachToRoot为true(参看inflate(int, android.view.ViewGroup, Boolean)方法)。

    4、Memory allocations

    有些地方是对性能非常敏感的,要减少创建java对象

    在管理对象的时候可以适当的使用软引用和弱引用

    Simple cache
    private final HashMap<String, SoftReference<T>> mCache;
    public put(String key, T value) {
     mCache.put(key, new SoftReference<T>(value));
     }
    public T get(String key, ValueBuilder builder) {
    T value = null;
    SoftReference<T> reference = mCache.get(key);
    if (reference != null) {
     value = reference.get();
     }
    // Not in cache or gc'd
    if (value == null) {
     value = builder.build(key);
     mCache.put(key, new SoftReference<T>(value));
     }
    return value;
     }
  • 相关阅读:
    vue中Axios的封装和API接口的管理
    如何配置Webpack/Vue-CLI实现前端跨域(附跨域大全)
    前端面试几个重要知识点
    js常用函数
    JS中的枚举和不可枚举
    可配置性属性和不可配置性属性
    Object.create()和深拷贝
    JavaScript 中 call()、apply()、bind() 的用法
    从深入到通俗:Object.prototype.toString.call()
    js原生实现三级联动下拉菜单
  • 原文地址:https://www.cnblogs.com/zhouliweiblog/p/3379453.html
Copyright © 2020-2023  润新知