3

我有一个相当令人费解的问题。如果我尝试使用 AsyncTask 填充 ListView,则永远不会调用该 ListView 适配器上的 getView()。请注意,这是 Activity 启动时此 ListView 的初始数据填充。AsyncTask 是必需的,因为 ListView 是从 HTTP 填充的。

我有以下简单的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >
<ListView  
    android:id="@+id/transactionListView"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:divider="#CCCCCC"
    android:dividerHeight="1px"
    />
</LinearLayout>

还有一个基本的 onCreate():

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mainListView = (ListView)findViewById(R.id.transactionListView);
    this.populateListView();
}

您可以看到调用:

private void populateListView()
{
    populateListViewTask task = new populateListViewTask();
    task.execute();
}

最后,AsyncTask onPostExecute():

protected void onPostExecute(Void result)
{
    lvAdapter = new CustomArrayAdapter(MainActivity.this, R.layout.listitem, data);
    mainListView.setAdapter(lvAdapter);
}

当然,实际的实现要复杂一些,但我已经消除了任何其他错误来源,除了在上述配置中没有调用 getView()。如果在 onPostExecute() 中添加 lvAdapter.getCount(),我得到 30(这是我所期望的,因为真实代码的 HTTP/XML 解析部分工作正常)。我也尝试添加 notifyDataSetChanged(),只是为了笑,但 CustomArrayAdapter 顾名思义,就是扩展 ArrayAdapter。我也在视图上尝试了 invalidate() ,也没有效果。

但是,如果在调用 AsyncTask 之前将 onCreate() 更改为具有单个虚拟列表项,如下所示:

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mainListView = (ListView)findViewById(R.id.transactionListView);

    //Add dummy list item
    TestDataStructure[] data = new TestDataStructure[1];|
    data[0] = new TestDataStructure();
    data[0].item = "Dummy List Item";
    lvAdapter = new CustomArrayAdapter(MainActivity.this, R.layout.listitem, data);
    mainListView.setAdapter(lvAdapter);

    this.populateListView();
}

getView() 将在 onPostExecute() 调用之后正确调用,ListView 将使用来自 AsyncTask 的新项目正确填充。我的预感是,在原来的情况下,Android 在 Activity 创建周期中确定了布局中项目的结构和可见性,并决定 transactionListView 因为它是空的而不可见,从而阻止它在新适配器时调用 getView()已设置。

关于如何在不添加虚拟列表项的情况下解决此问题的任何想法(在 AsyncTask 完成之前当然可见)?我的活动扩展了 Activity,而不是 ListActivity。

谢谢!

4

2 回答 2

1

如果您的数据是ArrayList<String>,您可以在onCreate()this中data = new ArrayList<String>();分配并使用此分配适配器,这将使您的 ListView 保持为空,直到您完成异步任务,您可以使用您的值分配数据,并通知适配器数据已更改为 this adapter.notifyDataSetChanged()

于 2012-04-19T01:41:08.293 回答
0

听起来和看起来您需要在填充适配器后在适配器上调用 notifyDataSetChanged() 。这必须从 UI 线程调用,所以将其放入从 postExecute() 方法直接调用的代码中。

如果这有帮助,请将其标记为答案。

于 2012-04-19T01:30:27.823 回答