android - 使用 Runnable 填充 ListView - 返回太多

标签 android arrays listview

我正在组装一个应用程序,它在 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/

相关文章:

Android 安全更改 UID

android - 从其依赖项中获取父应用程序的包名称和版本

android - 低功耗蓝牙 - notifyCharacteristicChanged() 不更新描述符值

java - NullPointerException,研究了也找不到原因

java - 奥利奥 : android. content.res.Resources$NotFoundException

javascript - D3.js 中可折叠树中的链接

c++使用foreach使数组为空

listview - NativeScript Angular 2 Firebase 列表不起作用

android - 如何在 Android 中隐藏 RSS ListView 浏览器

java - 如何在 ListView 中显示 arraylist 中的所有解析数据?