android - 在 OnClickListener 中刷新 Android ListView 数据

标签 android listview baseadapter notifydatasetchanged

我一直在 Android 中开发一个个人项目,并遇到了一个关于使用 ListView 的 Activity 的奇怪情况。问题的基础是我有一个项目列表,每个项目都有 2 个按钮,即编辑和删除。现在我正在努力实现“删除”按钮,该按钮可以正常工作,但无法正确更新 ListView。相反,它将刚刚删除的内容放在列表顶部。当然,每当我重新导航到该 Activity 时,它就会刷新。

现在,在自定义 BaseAdapter 内检测到“删除”按钮,当我调用 notificationDataSetChanged 时,会发生上述情况,而不是删除现在删除的项目。如何正确更新适配器类中的列表?

我意识到对此存在一些疑问,但我无法将它们整合起来,而且我认为可能有效的解决方案并不能真正解释它们是如何工作的;我正在使用这个项目来更多地了解 Android 应用程序开发,所以我更喜欢带有一定程度解释的答案,尽管当然感谢任何帮助! 谢谢!

这是相关代码。请注意,这是一个未完成的项目,因此其中有一些未使用/不完整的东西。请忽略这些。

编辑项目 Activity :

package com.example.mybudget;

import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;

public class EditItemsActivity extends Activity implements OnGestureListener{

    private DatabaseHandler db;
    private List<DataPoint> dpList;
    private EditItemsAdapter adapter;
    private ListView lv;
    private GestureDetector gestureDetector;

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_edit_items);
        // Show the Up button in the action bar.
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
            getActionBar().setDisplayHomeAsUpEnabled(true);
        db = new DatabaseHandler(this);
        dpList = db.allDataThisMonth();
        lv = (ListView) findViewById(R.id.edititems);
        adapter = new EditItemsAdapter(this, R.id.edititems, dpList);
        lv.setAdapter(adapter);
        gestureDetector = new GestureDetector(getBaseContext(), this);

//      buttonDelete.setVisibility(View.GONE);
    }

    public void refreshList()
    {
        adapter.notifyDataSetChanged();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_edit_items, menu);
        return true;
    }


    @Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

    public void onDelete()
    {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) 
    {
//      Log.d("Swipe", "" + velocityX + ", " + velocityY);
//      if(velocityX > 200 && velocityY < 50 && velocityY > -50)
//      {
//          buttonEdit.setVisibility(View.GONE);
//          buttonDelete.setVisibility(View.VISIBLE);
//      }
//      else if(velocityX < -200 && velocityY < 50 && velocityY > -50)
//      {
//          buttonDelete.setVisibility(View.GONE);
//          buttonEdit.setVisibility(View.VISIBLE);
//      }
        return false;
    }


    @Override
    public void onLongPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }


    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        // TODO Auto-generated method stub
        return false;
    }


    @Override
    public void onShowPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }


    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

}

这是适配器类:

package com.example.mybudget;

import java.text.NumberFormat;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

public class EditItemsAdapter extends BaseAdapter implements OnClickListener{
    private List<DataPoint> dpList;
    private Activity activity;
    private DatabaseHandler db;

    public EditItemsAdapter(Activity a)
    {
        activity = a;
    }

    public EditItemsAdapter(Activity a, int textViewResourceId, List<DataPoint> dpList)
    {
        super();
        this.dpList = dpList;
        activity = a;
        db = new DatabaseHandler(activity);
    }

    public static class ViewHolder
    {
        public TextView item1;
        public TextView item2;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View v = convertView;
        //ViewHolder holder;
        NumberFormat format = NumberFormat.getCurrencyInstance();

        if (v == null)
        {
//          LayoutInflater vi = 
//                  (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            LayoutInflater vi = activity.getLayoutInflater();
            v = vi.inflate(R.layout.edit_grid_items, null);
//          holder = new ViewHolder();
//          holder.item1 = (TextView) v.findViewById(R.id.edit_item_name);
//          holder.item2 = (TextView) v.findViewById(R.id.edit_item_cost);
//          v.setTag(holder);
            TextView tv1 = (TextView)v.findViewById(R.id.edit_item_name);
            TextView tv2 = (TextView)v.findViewById(R.id.edit_item_cost);
            Button edit = (Button)v.findViewById(R.id.edit_item_button);
            Button delete = (Button)v.findViewById(R.id.delete_item_button);
            final DataPoint dp = dpList.get(position);
            tv1.setText(dp.getName());
            tv2.setText(Float.toString(dp.getCost()));
            delete.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    db.deleteRowByKey(dp);
                    ((EditItemsActivity) activity).refreshList();
                }
            });
        }
//      else
//          holder = (ViewHolder)v.getTag();
//      if(dp != null)
//      {
//          holder.item1.setText(dp.getName());
//          holder.item2.setText(format.format(dp.getCost()));
//      }
        return v;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return dpList.size();
    }

    @Override
    public DataPoint getItem(int position) {
        // TODO Auto-generated method stub
        return dpList.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return dpList.size();
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

    }
}

编辑: 该解决方案涉及 Adam 提供的通货膨胀解释,但需要完全重新填充 dpList,即

dpList = db.allDataThisMonth();

Anup 建议的。

最佳答案

在适配器的 getView 方法中,您将检查 if (convertView == null) ,如果为 null,则将生成一个新 View 。如果它为空,则您只是返回所提供的非空 View 。

提供给getView方法的convertView是一个已经显示的缓存 View 。您应该重复使用它(如果它是一个有效的 View - 您的列表中可能有多个不同的 View ),而不是增加一个新 View 。您忘记更新相应位置的内容。

那么,如何解决呢?只需在通货膨胀后关闭您的 if (v == null) 即可:

if (v == null)
{
    LayoutInflater vi = activity.getLayoutInflater();
    v = vi.inflate(R.layout.edit_grid_items, null);
}

编辑:正如 Anup 指出的,您还需要更新 dpList 变量,否则它将继续为给定位置返回相同的值。您可以在点击监听器中执行此操作:

delete.setOnClickListener(new OnClickListener()
{
    @Override
    public void onClick(View v)
    {
        db.deleteRowByKey(dp);
        dpList.remove((Integer)v.getTag());
        ((EditItemsActivity) activity).refreshList();

    }
});
// Required so we know which index to remove from our dpList.
delete.setTag(position);

关于android - 在 OnClickListener 中刷新 Android ListView 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16849906/

相关文章:

java - 在 fragment 被分离然后重新附加后, fragment onResume 不会被调用

java - android java消费vb.net wcf服务

android - android.performFiltering() 过滤时出现 sql 异常。

c++ - 如何禁用 ListView 选择视觉效果并在项目周围绘制一个矩形?

android - 图库在 Gallery BaseAdapter 中的 notifydatasetchanged 上闪烁

java - Android L 5.0 和 libusb 1.0.9 - 没有权限?

android - 如何在 android 中对 JobScheduler 进行单元测试

java - 从 Api 加载图像并缓存它

java - 需要帮助在使用基本适配器的 ListView 上设置点击事件

Android ListView : Is it possible to add data to a few rows before-wards, 而 ListView 的其余部分是动态加载的吗?