【问题标题】:calling remove from custom adapter always removes last item从自定义适配器调用 remove 总是删除最后一项
【发布时间】:2014-12-26 23:27:50
【问题描述】:

我已经实现了一个自定义适配器和 listItemView。适配器将 onlclick 侦听器设置为 listItemView 上的按钮。 onclick 侦听器只是调用我在适配器中的私有方法并将要删除的项目的位置传递给它。我知道位置是正确的,因为数据库删除了正确的项目。我发现了类似的问题,但无法调整答案以适合我。非常感谢您的想法和想法。谢谢。

这是完整的适配器类

public class FoodListAdapter extends ArrayAdapter<FoodListItem> {

    //private
    private int type;

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
        super(context, 0, _objects);
        type = 0;       
    }

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
        super(context, 0, _objects);
        type = _type;       
    }

    @Override
    public View getView(int position, View reusableView, ViewGroup parent)
    {
        //Cast the reusable view to a listAdpaterItemView
        FoodListItemView listItemView = (FoodListItemView) reusableView;

        //Check if the listAdapterItem is null
        if(listItemView == null)
        {
            //If it is null, then create a view.
            listItemView = FoodListItemView.inflate(parent, this, type);
        }

        if (type == 2)
        {
            Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
            deleteButton.setTag(new Integer(position));
        }

        //Now we need to set the view to display the data.
        listItemView.setData(getItem(position));

        return listItemView;
    }
}

这是我在片段中使用的部分代码。请注意,我在 listAdapter 的类中有一个私有变量,但我认为我不需要它。

    private void displayListForDate(Calendar _date)
{
    //get the list view
    ListView listView = (ListView) getView().findViewById(1);
    //Clear the listview by removing the listadapter and setting it to null.
    //listView.setAdapter(null);

    //First we must get the items.
    Global global = (Global) getActivity().getApplicationContext();
    DietSQLiteHelper database = global.getDatabase();

    //Create a list to hold the items we ate. This list will then be added to the listView.
    final ArrayList<FoodListItem> consumedList;
    //Add the items to the array.
    consumedList = database.getConsumed(_date.getTimeInMillis());

    //Create an adapter to be used by the listView
    listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);

    //Add the adapter to the listView.
    listView.setAdapter(listAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            consumedList.remove(position);
            listAdapter.notifyDataSetChanged();
        }
    });
}

【问题讨论】:

  • 你在哪里从适配器中删除数据?
  • 在deleteItem()中我调用remove(item),这个方法在adapater类中。
  • 可以发一下remove(item)方法的代码吗?
  • remove方法是继承的,我没有实现或者覆盖它。
  • 你能发布完整的适配器代码吗?

标签: android android-listview android-adapter


【解决方案1】:

如果你没有实现 FoodListItem 的 "equals" 方法,请尝试实现它。

【讨论】:

  • 这个实现了,我通过调试器确保当参数的ID与项目本身匹配时返回true。
【解决方案2】:

我建议, 您只需更新基础数据,在您的情况下为ArrayList&lt;FoodItems&gt;

在您的适配器中制作这个简单的方法并进行更改:

private List<FoodListItem> myList = new ArrayList<FoodListItem>();

public FoodListAdapter(Context context, List<FoodListItem> myList) {
    super(context, 0, myList);
    type = 0;
    this.myList = myList;
}

public FoodListAdapter(Context context, List<FoodListItem> myList, int _type) {
    super(context, 0, myList);
    type = _type; 
    this.myList = myList;     
}

// Also update your getView() method to use myList!
@Override
public View getView(int position, View reusableView, ViewGroup parent)
{
   ...
   listItemView.setData(myList.get(position));

public void removeItem(int positio){
    if(myList != null){
        myList.remove(position);
    }
}

然后在课堂上,您正在创建适配器(Activity/Fragment),只需调用该方法即可。

// Update the underlying ArrayAdapter
adapter.removeItem(position);
// Notify the adapter, the data has changed
adapter.notifyDataSetChanged();

此外,您不应该在 UI 线程上打开与 SQLiteDatabase 的连接,因为您正在阻止它。你永远不知道,从磁盘读取的速度有多快。如果花费的时间太长,用户可能会认为您的应用程序冻结了,因此他离开了,这是您不想要的。我建议使用AsyncTask,你会发现很多examples

【讨论】:

  • 当适配器为您提供列表时,我希望自己远离实现列表。我还需要重写一些方法,我不会。另外,当我将 clickListener 添加到适配器中的按钮时,我将如何从我的片段中调用 remove;如果您查看列表中的每一行都有一个删除按钮。我将研究您对 AsyncTask 的建议,但是我不希望 UI 在数据更新之前继续运行。也许等待屏幕就足够了。
  • 我已按照您的建议进行了更改,但仍然遇到同样的问题。我一定是忽略了什么。
  • @n01d3a 看起来,您必须在 ListView 上设置 Listener 并从 ArrayList 中删除该项目。然后通知适配器,它应该正确刷新自己。这意味着,您在 Activity/Fragment 中执行此代码,而不是在适配器中。试试看这个:stackoverflow.com/questions/18444671/…
  • 我在列表中添加了一个 onitemClickListener,获取位置,然后从列表中删除位置处的项目。然后调用 notifyOnDataSetChagned。我将使用片段中的相关代码更新上面的帖子。
【解决方案3】:

我检查并清理了我的代码,现在它可以工作了,这是工作代码。除了更新用于分配和获取视图的 ID 之外,我真的不知道确切的区别。如果有人能解释我遇到问题的原因,我将不胜感激。

这是我的片段中的 sn-p,我在其中创建列表视图并分配一个适配器。

private void displayListForDate(Calendar _date)
{
    //get the list view
    ListView listView = (ListView) getView().findViewById(R.id.listView);
    //Clear the listview by removing the listadapter and setting it to null.
    //listView.setAdapter(null);

    //First we must get the items.
    Global global = (Global) getActivity().getApplicationContext();
    DietSQLiteHelper database = global.getDatabase();

    //Create a list to hold the items we ate. This list will then be added to the listView.
    ArrayList<FoodListItem> consumedList;
    //Add the items to the array.
    consumedList = database.getConsumed(_date.getTimeInMillis());

    //Create an adapter to be used by the listView
    listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);

    //Add the adapter to the listView.
    listView.setAdapter(listAdapter);
}

这是我的适配器类。

public class FoodListAdapter extends ArrayAdapter<FoodListItem> 
{

    //private
    private int type;

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
        super(context, 0, _objects);
        type = 0;       
    }

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
        super(context, 0, _objects);
        type = _type;       
    }

    @Override
    public View getView(int position, View reusableView, ViewGroup parent)
    {
        //Cast the reusable view to a listAdpaterItemView
        FoodListItemView listItemView = (FoodListItemView) reusableView;

        //Check if the listAdapterItem is null
        if(listItemView == null)
        {
            //If it is null, then create a view.
            listItemView = FoodListItemView.inflate(parent, type);
        }

        if (type == 2)
        {
            Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
            deleteButton.setTag(new Integer(position));
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Integer tag = (Integer) view.getTag();
                    deleteItem(tag.intValue());
                }
            });
        }

        //Now we need to set the view to display the data.
        listItemView.setData(getItem(position));

        return listItemView;
    }

    private void deleteItem(int position)
    {
        FoodListItem item = getItem(position);
        Global global = (Global) getContext().getApplicationContext();

        DietSQLiteHelper database = global.getDatabase();
        database.removeConsumed(item.getID());

        remove(getItem(position));
    }
}

【讨论】:

    猜你喜欢
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多