是否有人在Android中比较声明性(XML)与编程创建的UI的基准?
Google已采取措施加快声明性方法,但您仍然可以在运行时完成布局通胀步骤。
您是否曾因任何原因切换(或考虑)将UI从声明更改为程序化?
答案 0 :(得分:23)
在运行时很少完成布局膨胀。正如LayoutInflator API docs中所暗示的那样:
出于性能原因,请查看 通货膨胀严重依赖 预处理XML文件 在构建时完成。因此它是 目前无法使用 带有XmlPullParser的LayoutInflater 在运行时通过纯XML文件
如果您查看source,许多视图都会根据其XML标记从哈希映射中提取。
在回答你是否对inflater进行基准测试的问题时,我不得不说。就个人而言,我发现在Android中对应用程序的布局inflater进行基准测试的想法相当于在Firefox中为您的网站对DOM解析器进行基准测试。我不认为这个练习毫无意义,但你应该有一个比“我的活动布局对于inflater来说太复杂”更好的理由......
如果您需要动态生成的布局,最好以编程方式创建它。如果您的视图需要花费很长时间才能充气,那么您应该简化视图XML。
答案 1 :(得分:3)
我开发了这个类来预先扩充视图池并在每次需要时重用它。我在更新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);
}
}
答案 2 :(得分: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);
}
}