我有动态且非常大的内容,需要在用户交互中填充(点击下一页/上一页)。
动态内容以编程方式显示在myTableLayout上(参见下面的xml)。每次用户点击下一个/上一个
页面然后我调用myTableLayout.removeAllViews()
,做一些事情并重新填充myTableLayout.addView()
。
在内容较小的情况下,它会快速绘制,但如果填充大量内容,我会注意到两到三秒的延迟。
我已经看到了一个与我的功能相同的应用程序(也有相当大的内容),但它的分页速度非常快 甚至在低端设备上也是如此。
需要一些关于如何提高布局性能的建议。
感谢。
注意:Upper TableLayout用作标题(header),在它下面的LinearLayout是放置内容的地方。
<TableLayout
android:layout_width="fill_parent"
android:layout_height="45dip"
android:stretchColumns="0,2"
android:shrinkColumns="0,2"
>
<TableRow>
<LinearLayout
android:id="@+id/llLeft"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/tvLeft1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/llCenter"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/tvCenter1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
/>
<TextView
android:id="@+id/tvCenter2"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/llRight"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/tvRight1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<com.MyScrollView
android:id="@+id/myScrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TableLayout
android:id="@+id/**myTableLayout**"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1"
/>
</com.MyScrollView>
</LinearLayout>
以下是创建动态内容的代码。从内存中获取的内容(ArrayList)因此不应该是问题。
private void gotoPage() {
myTableLayout.removeAllViews();
GlobalVar g = GlobalVar.getInstance();
ArrayList<String> arrScripts = g.getDatasMap().get(SCRIPT_INDEX);
ArrayList<String> arrTrans = g.getTranslationMap().get(SCRIPT_INDEX);
Log.i(APP_NAME, "finished preparing data");
try {
// Data Title
tvCenter1.setText(arrScripts.get(0));
tvCenter2.setText(" (" + SCRIPT_INDEX + ")");
int countScripts = arrScripts.size();
for(int i=1; i<countScripts; i++) {
// Row Script
TableRow trScript = new TableRow(this);
trScript.setPadding(0, 5, 0, 0);
TextView tvIndex = new TextView(this);
tvIndex.setGravity(Gravity.CENTER);
tvIndex.setWidth(40);
tvIndex.setText("" + i);
TextView tvScript = new TextView(this);
tvScript.setGravity(Gravity.RIGHT);
tvScript.setTypeface(g.getFontTypeFace());
tvScript.setTextSize(FONT_SIZE);
tvScript.setPadding(0, 0, 5, 0);
tvScript.setText(arrScripts.get(i));
trScript.addView(tvIndex);
trScript.addView(tvScript);
TableRow trTrans = null;
if(IS_USE_TRANSLATION) {
// Row Translation
trTrans = new TableRow(this);
TextView tvBlank = new TextView(this);
tvBlank.setPadding(0, 0, 0, 5);
TextView tvTrans = new TextView(this);
tvTrans.setPadding(0, 0, 0, 5);
tvTrans.setText(arrTrans.get(i));
trTrans.addView(tvBlank);
trTrans.addView(tvTrans);
}
// Place for line separator
View vSep = new View(this);
ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
p.height = 3;
vSep.setLayoutParams(p);
// Combine rows to table
if(IS_USE_SCRIPT) myTableLayout.addView(trScript);
if(IS_USE_TRANSLATION) myTableLayout.addView(trTrans);
myTableLayout.addView(vSep);
}
} catch (Exception e) {
Log.e(APP_NAME, e.getMessage());
}
}
答案 0 :(得分:4)
我同意@ amplify91它可能来自生成内容,但您可能想要查看的其他内容之一是您正在使用的布局数量。基本思想是“越少越好”。你可以查看一些谷歌layout tricks
示例:我看到您的标题为table
,linearlayout
为textview
。 Relative layout
作为孩子的textviews
无法解决这个问题吗?
您将保存一些视图,并在布局树中保存一些“深度”。
答案 1 :(得分:2)
简单地说,完全摆脱TableLayout和TableRow以及TextView!
如果从Eclipse收集分析数据,您将看到大部分CPU /实时时间都来自TabletLayout和TextView的addView()方法。来电!
每次我用自定义实现替换TableLayout和TextView时,都会带来巨大的性能提升!
TextView应由自定义ViewView替换为自定义View,TableLayout。
编辑:我根据自己的需要创建了一些自定义视图。简单地说,我用onDraw()和onMeasure()方法覆盖了View类:
在下面的代码中,画家在静态构造函数中创建一次,textBaseline和textHeight也是如此,因为我对所有这些自定义“文本”视图使用单一字体大小。
@Override
protected void onDraw(Canvas canvas)
{
final int width = getWidth();
final float size = painter.measureText(innerText);
canvas.drawText(innerText, width - size - 5, textBaseline, painter);
if (underline)
{
canvas.drawLine(0, canvas.getHeight() - 1, canvas.getWidth(), canvas.getHeight() - 1, painter);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
if (innerText != null && painter != null)
{
switch (MeasureSpec.getMode(widthMeasureSpec))
{
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
w = (int)( (painter.measureText(innerText) + 5) );
break;
}
}
switch (MeasureSpec.getMode(heightMeasureSpec))
{
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
h = (int)( textHeight );
break;
}
setMeasuredDimension(w, h);
}
答案 2 :(得分:1)
我认为您应该通过Debug.startMethodTracing("xx")
和Debug.stopMethodTracing()
来调用您的代码,然后使用traceview
来了解正在发生的事情。其他一切都只是猜测。
答案 3 :(得分:0)
我想说延迟不是从XML构建布局,而是从生成动态内容。它是什么类型的内容?你可以发布一些代码吗?如果您从网站访问它,您可能需要预先获取它。如果您在更改页面时创建,则可能是您创建它的方式。
答案 4 :(得分:0)
如果您要做的只是以格式良好的表格格式添加文本(所有列自动调整大小等),请不要使用TableLayout,只需使用java.util.Formatter之类的内容将文本格式化为桌子形状。这需要一些预先工作,比如计算每列的最大字符串长度,但最终导致大的性能提升,因为您基本上将视图使用量减少到单个TextView(将活动加载到几乎瞬间约为2秒)。 / p>
例如:
// Compute max string length of each column
for (Entry entry : entries) {
if (entry.column1.length() > column1MaxLength) {
column1MaxLength = entry.column1.length();
}
...
if (entry.columnN.length() > columnNMaxLength) {
columnNMaxLength = entry.columnN.length();
}
}
// Formatter internally stores output string in StringBuilder
Formatter formatter = new Formatter();
// Construct table header
formatter.format("%1$" + column1MaxLength + "s", "Column 1 Title");
...
formatter.format("%1$" + columnNMaxLength + "s", "Column N Title");
// Add each entry into table
for (Entry entry : entries) {
formatter.format("%1$" + column1MaxLength + "s", entry.column1.value);
...
formatter.format("%1$" + columnNMaxLength + "s", entry.columnN.value);
}
// Get string representing formatted table from Formatter and put into TextView
textView.setText(formatter.toString());