【问题标题】:Android - Declarative vs Programmatic UIAndroid - 声明式与程序式 UI
【发布时间】:2010-04-01 14:10:47
【问题描述】:

有没有人看到或编译过比较声明式 (XML) 与 Android 中以编程方式创建的 UI 的基准?

Google 已经采取了一些措施来加速声明式方法,但您仍然需要在运行时完成布局膨胀步骤。

您是否曾经因任何原因切换(或考虑过)将您的 UI 从声明式更改为程序式?

【问题讨论】:

  • 与问题无关,但是为什么我的头像会变成粉红色的独角兽马和彩虹!那应该被禁止。是时候我自己设置一个了。
  • @jleedev 搞笑...我喜欢它。一定是愚人节玩笑,否则我被“独角兽蠕虫”击中
  • 我必须说今天早上看到我的头像时有点困惑...不过它为 StackOverflow 添加了更多颜色:)

标签: android performance


【解决方案1】:

很少有布局膨胀是在运行时完成的。正如 LayoutInflator API 文档中所暗示的:

出于性能原因,请查看 通货膨胀严重依赖 XML 文件的预处理 在构建时完成。因此它是 目前无法使用 带有 XmlPullParser 的 LayoutInflater 在运行时通过纯 XML 文件

如果您查看source,许多视图都是从基于其 XML 标记的哈希映射中提取的。

在回答您关于我是否对充气机进行基准测试的问题时,我不得不说不。就我个人而言,我发现为您的应用程序在 Android 中对布局充气器进行基准测试的想法等同于为您的网站在 Firefox 中对 DOM 解析器进行基准测试。我不认为这个练习没有意义,但你应该有一个比“我的活动布局对于充气机来说太复杂”更好的理由......

如果您需要动态生成的布局,最好以编程方式创建它。如果您的视图只是需要很长时间才能膨胀,您应该简化您的视图 XML。

【讨论】:

  • XML 文件也被编译成二进制文件,我们可以比普通 XML 快几个数量级。
【解决方案2】:

我开发了这个类来预膨胀视图池并在每次需要时重复使用它。在更新 UI 时,我的性能提升了几秒钟,这令人印象深刻。

我的 Logcat 说:

updating UI inflating on demand >> 2136mS
updating UI reusing from pool >> 937mS

这是我的课,别介意我笨拙的 Java 编码风格,我是 C++ 嵌入式程序员。

import java.util.ArrayList;
import java.util.List;
import android.view.LayoutInflater;
import android.view.View;

    public class ViewPool {
        private List<View> mViews;
        private LayoutInflater mInf;
        private int mIdx;
        private int mResource;

        /**
         * Constructor, gives Inflater and resource ID to inflate
         * @param mInf Layout inflater
         * @param rID  Resource ID of view to inflate
         * @para number number of views that must inflate on first initialization
         */
        public ViewPool(LayoutInflater mInf, int rID, int number) {
            super();

            int idx;
            mViews = new ArrayList<View>();
            this.mInf = mInf;
            mResource = rID;
            mIdx=0; // index of first used item

            for(idx=0; idx<number;++idx)
            {
                mViews.add((View)mInf.inflate(mResource, null));
            }

        }

        /**
         * Start from first item of pool
         */
        public void Reset()
        {
            mIdx=0;
        }

        /**
         * Get a view from pool, if no more views on pool, inflate more 
         * @return
         */
        public View GetView()
        {
            View retval;

            retval = mViews.get(mIdx);
            ++mIdx;

            if(mIdx == mViews.size()) // no more views in pool??
                mViews.add((View)mInf.inflate(mResource, null)); // inflate more

            return(retval);
        }       
    }

【讨论】:

    【解决方案3】:

    我对此进行了一些非常非正式/骇人听闻的测试,发现采用程序化方法虽然不太好用,但总时间减少了三分之一到一半。该测试仅在三星 7" Galaxy 上运行,而不是在 AVD 上运行。

    正如我所说,这是一个非常非正式/骇人听闻的测试(正如您将通过代码看到的那样),在非常有限的情况下,您可以快速组合起来以满足自己的好奇心,而不是通常用于公共消费。

    R.layout.ll 和 R.layout.tv 是简单的布局文件,分别包含空白的 LinearLayouts 和 TextViews。

    如果您只使用少数视图,我会坚持使用 XML/inflaters,但是如果速度是一个问题,那么对于数百个视图,您可能会想要考虑编程方法。

    package com.inflatervscode;
    
    import java.util.Calendar;
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class InflaterVSCodeActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    // Generates a few nested LinearLayouts/TextViews, a number of
    // times, and works out how many milliseconds this took.
    @Override
    public void onResume() {
        super.onResume();
        setContentView(R.layout.main);
    
        int num_repeats = 500; // Change this to however many times you want to
                               // create a set of nested views.
        LinearLayout masterLL = (LinearLayout)findViewById(R.id.test);
        TextView results = (TextView)findViewById(R.id.results);
    
        Calendar c = Calendar.getInstance();
        long startTime = c.getTimeInMillis();
    
        for (int i=0;i<num_repeats;i++) {
                // Replace the section below with LinearLayout fll = new LinearLayout(this); etc
            LinearLayout fll = (LinearLayout)getLayoutInflater().inflate(R.layout.ll, null);
            LinearLayout sll = (LinearLayout)getLayoutInflater().inflate(R.layout.ll, null);
            LinearLayout tll = (LinearLayout)getLayoutInflater().inflate(R.layout.ll, null);
            TextView tv = (TextView)getLayoutInflater().inflate(R.layout.tv, null);
    
            tv.setText(i+"");
            tll.addView(tv);
            sll.addView(tll);
            fll.addView(sll);
            masterLL.addView(fll);
        }
    
        c = Calendar.getInstance();
        long endTime = c.getTimeInMillis();
    
        String tt = Long.toString((endTime-startTime));
    
        results.setText("Results for "+num_tests+" tests:\n\nStart:"+Long.toString(startTime)+"\nEnd  :"+Long.toString(endTime)+"\n\nDifference (ms):"+tt);
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 2012-06-13
      • 2013-02-04
      • 2021-07-03
      相关资源
      最近更新 更多