我正在组装一个应用程序,它在 relativeLayout 中有一个 ListView ,里面有几个 LinearLayouts。所以我有我的适配器,以及一个将项目放入列表的函数。该函数只在app主进程的OnCreate函数中调用,在一个线程的runnable中调用。你们能看出为什么这个东西可能会多次调用添加到我的数组中吗? (当我只向数组添加一个东西时,for 循环被调用了数千次。 在主进程的 OnCreate 方法中:
array = new ArrayList<Item>(); //The misbehaving array
ListView lv = (ListView)findViewById(R.id.ItemList);
this.m_adapter = new ItemAdapter(this, R.layout.Itemlist_item, array);
lv.setAdapter(this.m_adapter);
viewItems = new Runnable(){
@Override
public void run() {
getItems();
}
};
Thread thread = new Thread(null, viewItems, "ListThread");
thread.start();
getItems 函数和第二个 Runnable:
private void getItems(){
try{
//Try Some Stuff
}
catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
private Runnable returnRes = new Runnable() {
@Override
public void run() {
if(array != null && array.size() > 0){
listAdapter.notifyDataSetChanged();
//This loop is where I'm seeing the problem
for(int i=0;i<array.size();i++) {
listAdapter.add(array.get(i));
}
}
}
};
和列表适配器:
public class ItemAdapter extends ArrayAdapter<Item> {
public ArrayList<Item> items;
public ItemAdapter(Context context, int textViewResourceId, ArrayList<Item> items) {
super(context, textViewResourceId, items);
this.items = items;
}
@Override
public View getView(int position, View conView, ViewGroup parent) {
View v = conView; //The content view
if (v == null){
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.itemlist_item, null);
}
Item o = items.get(position);
if (o != null){
TextView name = (TextView)v.findViewById(R.id.item_name);
if(name != null){
name.setText("name:"+o.getItemName());
}
}
return v;
}
}
非常感谢任何帮助。 谢谢, -克里斯
最佳答案
问题是 ListView
和其他与适配器一起工作的此类 UI 小部件不允许适配器的内容在它们上意外更改。您需要在 ListView
下次尝试与您的适配器交互之前告知您所做的更改。如果您允许另一个线程修改适配器,或者在主线程上修改它但不在允许任何其他事情发生之前将更改告知 ListView
,您将随机(由于竞争)获得异常由 ListView
抛出适配器意外更改。
相反,像这样的东西应该可以工作(来自 HackBod 的帖子 here ):
public class MyAdapter extends BaseAdapter<Item> {
private ArrayList<Item> mItems;
public int getCount() {
return mItems != null ? mItems.size() : 0;
}
public MyItem getItem(int position) {
return mItems.get(i);
}
/* ... */
}
然后用
填充ListView
private Handler mHandler = new Handler();
private void setDataFromThread(ArrayList<Item> data) {
// Enqueue work on mHandler to change the data on
// the main thread.
mHandler.post(new Runnable() {
@Override
public void run() {
mItems = newData;
notifyDataSetChanged();
}
});
}
关于android - 使用 Runnable 填充 ListView - 返回太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11371820/