Android - 使用ArrayAdapter一次向ListView添加和显示项目

时间:2010-01-25 06:15:48

标签: android listview android-listview android-asynctask android-arrayadapter

我正在使用ArrayAdapter将项目添加到自定义ListView并在我的Android应用程序中显示结果。我遇到的问题是ArrayAdapter在显示视图之前似乎要等到所有项目都在其中。也就是说,当我将项添加到ArrayAdapter并调用notifyDataSetChanged时,它不会更新ListView以显示添加的项。它等待直到添加所有项目并在显示项目之前调用GetView。

我希望它能在将项目添加到ListView后立即显示该项目。这可能吗?

我相信相关的代码如下:

r_adapter = new ReminderAdapater(Activity_ContentSearch.this, R.layout.search_listitem, myList);
listView.setAdapter(r_adapter);
...
r_adapter.notifyDataSetChanged();
r_adapter.clear();
for(int i = 0; i < myList.size(); i++)
{
    r_adapter.add(myList.get(i));
    r_adapter.notifyDataSetChanged();
}

正如您所看到的,即使我在add方法之后调用notifyDataSetChanged,它实际上也不会更新视图。在完成上面的循环之后,视图最终被更新(基于我所知道的,这是因为在完成代码的这一部分之后才调用GetView)。

我试图覆盖自定义ArrayAdapter的add方法而没有运气,因为我无法访问该方法中的视图。

欢迎任何帮助:)

巴拉

1 个答案:

答案 0 :(得分:23)

Android的UI是单线程的。每次向适配器添加条目时,您都无法从主应用程序线程将控制权交还给Android。因此,在您返回控件之前,Android没有机会显示您的条目,并且在您完全填充适配器之前,您不会这样做。

Here is an example显示使用AsyncTask通过后台线程逐步填充ArrayAdapter

/***
  Copyright (c) 2008-2012 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain   a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder's Guide to Android Development_
    http://commonsware.com/Android
*/

package com.commonsware.android.async;

import android.app.ListActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import java.util.ArrayList;

public class AsyncDemo extends ListActivity {
  private static final String[] items={"lorem", "ipsum", "dolor",
                                      "sit", "amet", "consectetuer",
                                      "adipiscing", "elit", "morbi",
                                      "vel", "ligula", "vitae",
                                      "arcu", "aliquet", "mollis",
                                      "etiam", "vel", "erat",
                                      "placerat", "ante",
                                      "porttitor", "sodales",
                                      "pellentesque", "augue",
                                      "purus"};
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    setListAdapter(new ArrayAdapter<String>(this,
                        android.R.layout.simple_list_item_1,
                        new ArrayList<String>()));

    new AddStringTask().execute();
  }

  class AddStringTask extends AsyncTask<Void, String, Void> {
    @Override
    protected Void doInBackground(Void... unused) {
      for (String item : items) {
        publishProgress(item);
        SystemClock.sleep(200);
      }

      return(null);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onProgressUpdate(String... item) {
      ((ArrayAdapter<String>)getListAdapter()).add(item[0]);
    }

    @Override
    protected void onPostExecute(Void unused) {
      Toast
        .makeText(AsyncDemo.this, "Done!", Toast.LENGTH_SHORT)
        .show();
    }
  }
}