我正在开发一个Android应用,其中有一些列表。它比我在这里要解释的要复杂得多,但是我发布的场景也表现出异常。
我一直在浏览Stack Overflow中的几个问题,但找不到解决这个问题的方法。
因此,出于问题的考虑,我建立了这种情况。我有一个带有字符串数组的Activity,如下所示:
public class TestViewlazyloadActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String[] items = { "lorem", "ipsum", "dolor", "sit", "amet" };
ListView list = (ListView) findViewById(R.id.testListView);
TestAdapter adapter = new TestAdapter(this, R.layout.list_item, items);
list.setAdapter(adapter);
}
}
作为我的两种布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/testListView"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
这样:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/testTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
很简单然后,我用ViewHolder的想法实现了ArrayAdapter类,该方法的getView()方法如下:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
String item = this.getItem(position);
if(convertView == null) {
LayoutInflater inflater = ((Activity) this.getContext()).getLayoutInflater();
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.textView = (TextView) convertView.findViewById(R.id.testTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final ViewHolder auxHolder = holder;
LoadingService.capitalizeItemWithDelay(item, new LoadedCallback() {
public void onItemLoaded(String item) {
auxHolder.textView.setText(item);
}
});
return convertView;
}
LoadedCallback
仅是onItemLoaded
的接口。而LoadingService.capitalizeItemWithDelay()
只是启动一个线程,该线程随机睡眠一段时间(以模拟延迟加载),并使用大写String调用此回调。正常行为应该是用户正在查看包含5个空白行的列表。在一些时间之后,即使在给定随机睡眠计时器的情况下,它们也以随机顺序开始在它们各自的行中生成。
真正发生的是,项目被逐行加载到第一行,最终其中的一些被放置在实际位置。就像
auxHolder
在其TextView中保留对第一个元素的引用一样,这很奇怪。我了解这是由于视图被回收或由于auxHolder
被final
所致。有任何想法吗?提前致谢。
最佳答案
除去final
变量上的ViewHolder
并将ViewHolder auxHolder
移入内部类。
尝试这个:
...
LoadingService.capitalizeItemWithDelay(item, new LoadedCallback() {
ViewHolder auxHolder = holder;
public void onItemLoaded(String item) {
auxHolder.textView.setText(item);
当您将
final
关键字与局部变量(如auxHolder
)一起使用时,是说您给它提供的值是它将拥有的最后一个值。这就是您遇到问题的原因。这是一个可以解释得更好的链接:http://www.javapractices.com/topic/TopicAction.do?Id=23