【问题标题】:notifyDataSetChange does not refresh ListView with custom adapternotifyDataSetChanged 不使用自定义适配器刷新 ListView
【发布时间】:2014-06-12 20:06:38
【问题描述】:

我正在尝试解决这个问题,但我只是看不出我做错了什么。我想用产品动态填充 ListView(将产品添加到数组然后刷新列表,基本上每次单击都会将一个产品添加到数组,然后在 ListView 中显示数组的内容),它位于第二个片段中,其中包含来自第一个片段的数据。传递数据正在工作(使用日志确认),但我的主要问题是更新具有自定义适配器的 ListView。有了这段代码,什么都没有发生(ViewList 没有刷新,我可以看到每个日志(以及其他所有工作)并且没有错误)。 这是代码(所有这些都在第二个片段中):

此代码是全局的

ReceiptListAdapter receiptListAdapter; 
ArrayList<ReceiptItem> receiptItemArrayList;
int cat = 0;
int prodct = 0;

有了这个,我从第一个片段(到这个第二个片段)中得到 2 个数字

public void use(int num1, int num2) {
     Log.d("LOG","Category: " + num1 + "Product: "  + num2); //This works
     cat = num1;
        prodct = num2;

    ListView receiptItemListView = (ListView) getView().findViewById(
                R.id.receiptItemsList);
        receiptItemArrayList = (ArrayList<ReceiptItem>)generateReceiptItemsForTest();

        receiptItemListView.setAdapter(receiptListAdapter); //i think here is the problem

             receiptListAdapter.notifyDataSetChanged();    

}

OnViewCreated

public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    ListView receiptItemListView = (ListView) getView().findViewById(
            R.id.receiptItemsList);




    receiptItemArrayList = (ArrayList<ReceiptItem>) generateReceiptItemsForTest();

    receiptListAdapter = new ReceiptListAdapter(
            getActivity().getBaseContext(), R.layout.receipt_item,
            receiptItemArrayList);



    receiptItemListView.setAdapter(receiptListAdapter);


    TextView txtTotalAmmount = (TextView) getView().findViewById(
            R.id.txtReceiptTotalAmmount);
    double totalAmmount = getTotalAmmount(receiptItemArrayList);
    totalAmmount = Math.round(totalAmmount * 100) / 100;
    txtTotalAmmount.append(String.valueOf(totalAmmount));

}

private List<ReceiptItem> generateReceiptItemsForTest() { 
    List<ReceiptItem> receiptItemList = new ArrayList<ReceiptItem>();

    DatabaseAdapter db = new DatabaseAdapter(getActivity());




    if(cat != 0 && prodct != 0 )
    {

    name = db.readFromCategoriesAndGetOnePreduct(cat, prodct).getName();
    price = db.readFromCategoriesAndGetOnePreduct(cat, prodct).getPrice();
    Log.d("Name: " + name,"Price: " + String.valueOf(price)); //Also working (showing what i want) and i can see it in log but the ListView isnt refreshing this data

    receiptItemList.add(new ReceiptItem(name,1,price,1);


    }
                }


    return receiptItemList;
}



private double getTotalAmmount(ArrayList<ReceiptItem> receiptItems) {
    double totalAmmount = 0;
    for (ReceiptItem receiptItem : receiptItems) {
        totalAmmount += receiptItem.getTotalPrice();
    }
    return totalAmmount;
}

ReceiptListAdapter

public class ReceiptListAdapter extends ArrayAdapter<ReceiptItem> {

private Context context;

public ReceiptListAdapter(Context context, int rowResourceId,
        ArrayList<ReceiptItem> items) {
    super(context, rowResourceId, items);
    this.context = context;
}

@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;



    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.receipt_item, null);
    }

    ReceiptItem item = getItem(position);
    if (item != null) {
        TextView itemDescription = (TextView) view
                .findViewById(R.id.txtReceiptItemDescription);
        TextView itemAmmount = (TextView) view
                .findViewById(R.id.txtReceiptItemAmmount);
        TextView itemPrice = (TextView) view
                .findViewById(R.id.txtReceiptItemPrice);
        TableRow listItem = (TableRow) view
                .findViewById(R.id.trReceiptItem);
        if (position % 2 == 0)

listItem.setBackgroundDrawable(view.getResources().getDrawable(
                    R.drawable.list_item_selector_a));
        else
                listItem.setBackgroundDrawable(view.getResources().getDrawable(
                    R.drawable.list_item_selector_b));

        itemDescription.setText(item.getDescription());
        itemAmmount.setText(String.valueOf(item.getAmmount()));
        itemPrice.setText(String.format("%.2f", item.getPrice()));
    }

    return view;
}

 }

只有在我使用此代码时才能更新列表

receiptListAdapter = new ReceiptListAdapter(getActivity().getBaseContext(),R.layout.receipt_item,

而不是

receiptItemListView.setAdapter(receiptListAdapter);

但它只添加一次并在点击时再次刷新列表,但我知道为什么。

【问题讨论】:

  • 何时何地调用“使用”方法
  • 它用于从第一个片段中获取 2 个数字(当我单击类别然后单击第一个片段中的产品时,它会获取该数字并将它们放入 catprodct 并且这是我检查的工作带日志)
  • 为什么不使用 [Simple]CursorAdapter ?您的数据模型是 sqlite db,因此 CursorAdapter 是显而易见的使用

标签: android android-fragments android-listview


【解决方案1】:

您可以发布 ReceiptListAdapter 代码吗?这就是您需要在数据源和 UI 之间建立连接的地方。为此,您可以在数据库上注册 ContentObserver,然后 ListView 将其 ContentObserver 注册到 Adapter。 Adapter通过调用ListView DataSetObserver的onChanged()方法通知ListView更新。

使用数据库时,一个常见的选择是使用 CursorLoader 在与 CursorAdapter 配对的后台线程上从数据库中获取数据。 CursorLoader 会自动向数据库注册以收到更改通知。然后,您实现 LoaderManager 回调,它会告诉您数据集何时更改并向您传递更新的光标。然后在 CursorAdapter 上调用 swapCursor(cursor),将新光标传递给它,它会通知 ListView DataSetObserver 数据集已更改。 ListView 然后查询适配器以获取新值并刷新 UI。

查看本教程以获得一些很好的示例代码:http://www.vogella.com/tutorials/AndroidSQLite/article.html

【讨论】:

  • 我正在使用 ReceiptListAdapter 来格式化行。我只需要从这个活动的数据库中读取,基本上就可以用产品填充数组(在第一个片段上单击它的读取类别和数据库中的产品),然后我会使用该数组来填充收据,我有包括代码。
  • 看起来您实际上并没有更改适配器中的数据,因此即使您调用 'receiptListAdapter.notifyDataSetChanged();'存储在适配器中的数组仍然具有旧数据。您可以调用receiptListAdapter.add(Object) 或insert(Object,int) 将第二项添加到数组中,或者您应该能够使用更新的数组创建适配器的新实例,然后在ListView 上设置新适配器.
【解决方案2】:

我发现我必须让这个全球性 List&lt;ReceiptItem&gt; receiptItemList = new ArrayList&lt;ReceiptItem&gt;(); 我还要感谢 middleseatman 解释了一些事情,它真的帮助了我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多