Android:带有自定义 ArrayAdapter 的 ListView 在长列表上起作用 - 计时问题!
大家好,
我有这个“搜索结果”ListView。 搜索结果可以是不同的“种类”(不同的部分,称之为不同的部分)。 为了分隔“种类”,我添加了带有标题的行。 (我知道可扩展列表,但由于其他原因无法使用它)。
在 getView() 中,我检查一个属性,如果已设置,我会更改该行的背景颜色。
问题:当我运行一个仅返回几行(比如 15 行)的查询时,一切都很好。但是,当我运行另一个返回的内容(比如 600 行)时,有些东西变得很奇怪,它会以一定的规律间隔随机更改背景。当我在调试模式下运行并在中间停止时,也会发生同样的事情。
所以,这绝对是一个时间问题。
我认为这可能是由于屏幕键盘关闭时必须重新渲染大列表所致。
那么,是适配器的错吗?有什么解决办法吗?
如果键盘是问题所在,是否有一种机制可以在开始渲染之前告诉列表“等到事物关闭”? (不确定我喜欢这样,但这比得到一个可爱的小彩虹更好......)
谢谢!
Llappall——
==
这是适配器和元素布局(如下):
private class ElementAdapter extends ArrayAdapter<Element> {
private ArrayList<Element> rows;
private Element.typeEnum type;
public ElementAdapter(Context context, int textViewResourceId, ArrayList<Element> rows) {
super(context, textViewResourceId, rows);
this.rows = rows;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.element, null);
}
Element row = rows.get(position);
if (row == null) {
return v;
}
v.setTag(row);
type = row.getType();
boolean isSectionType = type == Element.typeEnum.DIV118SECTION || type == Element.typeEnum.APPASECT ||
type == Element.typeEnum.APPBSECT || type == Element.typeEnum.AZSECT;
TextView title = (TextView) v.findViewById(R.id.title);
TextView body = (TextView) v.findViewById(R.id.body);
if (isSectionType) {
body.setMaxLines(5000);
}
title.setText(row.getTitle());
if (row.getBody() != null) {
body.setText(row.getBody());
}
if (type == Element.typeEnum.SEARCHLISTHEADER) {
v.setBackgroundColor(Color.rgb(230, 230, 250));
title.setBackgroundColor(Color.rgb(230, 230, 250));
body.setBackgroundColor(Color.rgb(230, 230, 250));
star.setBackgroundColor(Color.rgb(230, 230, 250));
}
return v;
}
}
ELEMENT LAYOUT==
<TextView
android:id="@+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
style="@style/ListItemSubTitle" />
</LinearLayout>
HI all,
I have this "search results" ListView.
The search results can be of different "kinds" (different sections, call it).
To separate the "kinds" I add a row with a title. (I know about the expandable list, but can't use it for other reasons).
In my getView(), I check for a property, and if it's set, I change the background color of the row.
The problem: when I run a query that returns just a few rows (say 15), everything is fine. But when I run another that returns, say 600 rows, something goes wacko and it changes the background randomly, at a somewhat regular interval. Same thing happens when I'm running in debug mode and stop things in the middle.
So, it's definitely a timing issue.
I'm thinking this might be due to having to re-render the big list as the on-screen keyboard closes.
So, is the Adapter to blame? Is there any solution for this?
If the keyboard is the problem, is there a mechanism to tell the list "wait until the thing closes" before start rendering? (Not sure I like that, but it's better than getting a cute little rainbow...)
Thanks!
Llappall
--
Here's the adapter and the element layout (below):
private class ElementAdapter extends ArrayAdapter<Element> {
private ArrayList<Element> rows;
private Element.typeEnum type;
public ElementAdapter(Context context, int textViewResourceId, ArrayList<Element> rows) {
super(context, textViewResourceId, rows);
this.rows = rows;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.element, null);
}
Element row = rows.get(position);
if (row == null) {
return v;
}
v.setTag(row);
type = row.getType();
boolean isSectionType = type == Element.typeEnum.DIV118SECTION || type == Element.typeEnum.APPASECT ||
type == Element.typeEnum.APPBSECT || type == Element.typeEnum.AZSECT;
TextView title = (TextView) v.findViewById(R.id.title);
TextView body = (TextView) v.findViewById(R.id.body);
if (isSectionType) {
body.setMaxLines(5000);
}
title.setText(row.getTitle());
if (row.getBody() != null) {
body.setText(row.getBody());
}
if (type == Element.typeEnum.SEARCHLISTHEADER) {
v.setBackgroundColor(Color.rgb(230, 230, 250));
title.setBackgroundColor(Color.rgb(230, 230, 250));
body.setBackgroundColor(Color.rgb(230, 230, 250));
star.setBackgroundColor(Color.rgb(230, 230, 250));
}
return v;
}
}
==ELEMENT LAYOUT==
<TextView
android:id="@+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
style="@style/ListItemSubTitle" />
</LinearLayout>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您在此处发布 getView() 方法会容易得多。
据我所知,您可能错误地使用了回收视图。
如果未设置属性,请检查背景是否更改为某些内容。
例如:
如果您重用convertView,则单独使用将是错误的,因为当该视图用于不同的行时,背景将保持与原来相同的颜色。
一定是这样的:
It would be much easier if you would post a getView() method here.
From what I can tell, you might be using recycled views wrong.
Check if background is changed to something if property is not set.
For example:
Just by itself will be wrong if you are reusing convertView, since the background will stay the same color how it was, when this view was used for a different row.
must be something like:
我冒昧地为你重写了这段代码,因为你做了太多奇怪的东西。这是我认为适合您情况的优化工作代码(没有测试任何内容,但应该可以工作):
关于原始代码的一些注释:
if (row == null) {
返回v;
}
是错误的。对于列表中的任何位置,列表中不应有任何空元素。即使有,您也不应该只是为该行提供一些随机视图。您在这里所做的就是返回“v”,它很可能(并且可能是)一些回收的旧行,仍然显示旧数据,这会让用户感到困惑。我假设编写代码时不会有任何空元素。
几乎没问题,但同样,如果您重用convertView(这是不再显示的一些随机的前一行),那么如果body实际上为空,您将只显示旧数据,这又会让用户感到困惑。如果 body 为 null,则将字符串设置为空。
聚苯乙烯
我建议您观看此内容,了解有关如何使用 ListView 的提示和技巧:ListView 的世界
I took a liberty to rewrite that code for you, since you make too much weird stuff. Here's what I think is a optimized working code for your situation (didn't test any of it, but should work):
Couple of notes on the original code:
if (row == null) {
return v;
}
is wrong. You shouldn't have any null elements in your list for any position in the list. Even if you have, you shouldn't just throw some random view for the row. What you are doing here, is returning "v", that can very well be (and probably will be) some recycled old row, that still displays old data, and that's going to confuse the user. I made an assumption that you won't have any empty elements when wrote the code.
Is almost ok, but again, if you are reusing convertView (which is some random previous row that isn't displayed anymore), then if body is actually null you will just be displaying the old data, which again will confuse the user. If body is null, just set the string empty.
P.S.
I recommend you to watch this for tips and tricks about how to work with ListView: The world of ListView