2

我正在组合一个应用程序,该应用程序在 relativeLayout 中有一个列表视图,其中有几个 LinearLayouts。所以我有我的适配器和一个将项目放入列表的功能。该函数只在apps主进程的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;

        }

    }

任何帮助深表感谢。谢谢,-克里斯

4

1 回答 1

0

问题是ListView与适配器一起使用的其他此类 UI 小部件不允许适配器的内容在它们上发生意外更改。在下次尝试与适配器交互之前,您需要告知ListView您所做的更改。如果您允许另一个线程修改适配器,或者在主线程上修改它,但在允许其他任何事情发生之前不告知ListView更改,您将随机(由于竞争)收到ListView有关适配器意外更改的异常。

相反,这样的事情应该可以工作(来自 HackBod 的帖子

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();
        }
    });
}
于 2012-07-10T14:59:27.400 回答