简体   繁体   English

使用ListView的事件滚动加载更多数据时出错

[英]Error when load more data with event scroll of listview

I have problem with scroll of listview. 我在滚动列表视图时遇到问题。 I have a class like: 我有一个像这样的课程:

private int itemsPerPage = 6;
private int count = 0;
private boolean loadingMore = false;
private ArrayList<Item> item;
private ListItemAdapter adapter;
View footerView;
private JSONArray array;
private String json;

protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu);
    lvListItem = (ListView) findViewById(R.id.lvListItem);
    item = new ArrayList<Item>();
    footerView = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_footer, null, false);

    json = new JSONParse()
                    .getData("....");
    array = new JSONArray(json);

    load();
    adapter = new ListItemAdapter(this, 0, item);
    lvListItem.addFooterView(footerView);
    lvListItem.setAdapter(adapter);

    lvListItem.setOnScrollListener(new OnScrollListener() {

        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // TODO Auto-generated method stub

        }

        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            // TODO Auto-generated method stub
            int lastInScreen = firstVisibleItem + visibleItemCount;

            // is the bottom item visible & not loading more already ? Load
            // more !
            if ((lastInScreen == totalItemCount) && !(loadingMore)) {
                Thread thread = new Thread(null, loadData);
                thread.start();
            }
        }
    });
    }

public void load(){
for (int i = 0; i < itemsPerPage; i++) {
    if (count == array.length()) {
        lvListItem.removeFooterView(footerView);
        break;
    }
    /*****Code to load data*******/
}
}


private Runnable loadData = new Runnable() {
    @Override
    public void run() {

        loadingMore = true;


        item = new ArrayList<Item>();


        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        load();


        runOnUiThread(returnRes);

    }
};


private Runnable returnRes = new Runnable() {
    @Override
    public void run() {


        if (item != null && item.size() > 0) {
            for (int i = 0; i < item.size(); i++)
                adapter.add(item.get(i));
        }


        if (count == array.length())
            lvListItem.removeFooterView(footerView);
        adapter.notifyDataSetChanged();

        // Done loading more.
        loadingMore = false;
    }
};

if i just using load() , it run and listview show data ok. 如果我只是使用load() ,它将运行,并且listview显示数据正常。 But when I scrolling listview, it throw error: 但是当我滚动列表视图时,它会抛出错误:

  D/AndroidRuntime(1635): Shutting down VM W/dalvikvm(1635): threadid=1: thread exiting with uncaught exception (group=0x40a13300) E/AndroidRuntime(1635): FATAL EXCEPTION: main E/AndroidRuntime(1635): java.lang.IndexOutOfBoundsException: Invalid index 6, size is 6 E/AndroidRuntime(1635): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) E/AndroidRuntime(1635): at java.util.ArrayList.get(ArrayList.java:304) 

I need a help 我需要帮助

It seems like your array has only 6 elements and you are trying to access the element with index 6 which is effectively the 7th element so 看来您的数组只有6个元素,并且您正在尝试访问索引为6的元素,实际上它是第7个元素,因此

Change 更改

itemsPerPage = 5;` 

Your code is not threadsafe at all. 您的代码根本不是线程安全的。 You are accessing shared data from multiple threads without any kind of locking. 您正在从多个线程访问共享数据,而没有任何类型的锁定。 It is possible that your item array is being reinitialized in your worker thread while it is being read from in your resultRes runnable (running on the main thread), which would result in seemingly impossible out of bounds exceptions. 在从resultRes可运行(在主线程上运行)中读取item数组时,可能会在工作线程中将item数组重新初始化,这将导致看似不可能的超出范围的异常。

Create an object to use as your mutex: 创建一个用作互斥对象的对象:

private final Object monitor = new Object(); // an ivar in your Activity

Then when accessing shared data (like item and loadingMore ), create a critical section, for example: 然后,当访问共享数据(例如itemloadingMore )时,创建一个关键部分,例如:

synchronized(monitor) {
    item = new ArrayList<Item>();
}

synchronized(monitor) {
    if (item != null && item.size() > 0) {
        for (int i = 0; i < item.size(); i++)
            adapter.add(item.get(i));
    }
}

synchronized(monitor) {
    if ((lastInScreen == totalItemCount) && !(loadingMore)) {
        Thread thread = new Thread(null, loadData);
        thread.start(); // will exit critical section before new thread execution begins
    }
}

And so on. 等等。 I'll leave it as an exercise for you to figure out where the rest of the locking should be done. 我将把它留作练习,让您弄清楚应该在哪里进行其余的锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM