Android Volley ListView 闪烁和剩余项目

Android Volley ListView Blinking and Items Remaining

我有一个设置了 CustomAdapterListView,它显示了一个 json 对象数组,我用 volley 请求调用这些对象:

final ListView listView = (ListView) findViewById(R.id.list);

adapter = new CustomListAdapter(this,personList);
listView.setAdapter(adapter);

// Creating volley request obj
     final JsonArrayRequest personReq = new JsonArrayRequest(url,
        new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                Log.d(TAG, response.toString());

                // Parsing json
                for (int i = 0; i < response.length(); i++) {
                    try {

                        JSONObject obj = response.getJSONObject(i);
                        person.setfirstName(obj.getString("first_name"));
                        person.setlastName(obj.getString("last_name"));

                        //Add person to list
                        personList.add(person);
                        adapter.notifyDataSetChanged();

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }

                Log.i(TAG, "personList items: " + personList.size());


            }
        }, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        VolleyLog.d(TAG, "Error: " + error.getMessage());
        hidePDialog();

    }
});

    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(personReq);

使用可运行对象和处理程序,我每 5 秒发出一次此请求:

    //Run volley request every 5 seconds
    Runnable runnable = new Runnable() {
        @Override
        public void run() {

            if (orderList != null) {
                orderList.clear();
            }

            //Placing here TOO removes the last item but causes blinking
            //adapter.notifyDataSetChanged();

            AppController.getInstance().addToRequestQueue(personReq);

            handler.postDelayed(this, 5000);

        }
    };

    handler.postDelayed(runnable, 5000);

问题是一个项目总是保留,即使它不应该存在(由于通过单独的截击请求将其删除)。点击该项目会导致应用程序崩溃,并显示 logcat 中的以下内容:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.

如你所见,我正在调用 adapter.notifyDataSetChanged();添加一个人对象后直接。它工作正常,直到列表中的最后一项消失(但仍然可见)。

在 Runnable 中添加 adapter.notifyDataSetChanged(); 会清除最后一项,但会导致整个视图每 5 秒闪烁一次。

甚至可以防止这种闪烁吗?

试试这个。

在您的适配器中。

public void addAll(List<T> datas) {
    if (datas != null) {
        mData.addAll(datas);
        notifyDataSetChanged();
    }
}

然后在你的 Activity.

personList.add(person);
adapter.addAll(personList);
adapter.notifyDataSetChanged();

确保您的适配器在其内容更改时调用 notifyDataSetChanged()

As you can see, I am calling adapter.notifyDataSetChanged(); directly after adding a person object.

那太浪费了。调用notifyDataSetChanged一次,在列表处于您要显示的最终状态后。

Adding adapter.notifyDataSetChanged(); inside the Runnable does clear the last item but causes the whole view to blink every 5 seconds.

Is it even possible to prevent this blinking?

我只能猜测这 "blinking" 是因为您在发出网络请求之前清除列表并刷新适配器(从而使 ListView 为空),这当然会有一个根据网络情况延迟。

为什么不在发出网络请求之前清除您的列表,为什么不在响应返回后清除它?

public void onResponse(JSONArray response) {
    Log.d(TAG, response.toString());

    personList.clear(); // Wipe the list before adding new data

    // Parsing json
    // The rest of your parsing code here...

    // Now that the list is fully updated to the new state, call this ONCE
    adapter.notifyDataSetChanged();
}

好的,我想出了一个停止闪烁和清除最后剩余项目的方法。

除了onResponse方法之外,adapter.notifyDataSetChanged();也必须存在于onErrorResponse方法中。