在OnClickListener中刷新Android ListView数据

时间:2013-05-31 04:46:05

标签: android listview baseadapter notifydatasetchanged

我一直在Android上开展个人项目,并遇到一个使用ListView的Activity的奇怪情况。问题的基础是我有一个项目列表,每个项目有2个按钮,编辑和删除。现在我正在实现删除按钮,它在功能上有效,但不能正确更新ListView。相反,它将刚刚删除的内容放在列表顶部。每当我重新开始那项活动时,它当然会刷新。

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

我意识到对此有一些疑问,但我无法整合它们,我认为可行的解决方案并没有真正解释它们是如何工作的;我正在使用这个项目更多地了解Android应用程序开发,所以我更喜欢有一定程度解释的答案,尽管任何帮助当然都值得赞赏! 谢谢!

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

EditItemsActivity:

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建议。

2 个答案:

答案 0 :(得分:3)

在适配器的getView方法中,您正在检查if (convertView == null),如果它为空,则表示您正在为新视图充气。如果不是 null,则只返回提供的非空视图。

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

那么,如何修复呢?通货膨胀后只需关闭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);

答案 1 :(得分:2)

从您的代码中,我可以看到您的适配器由dplist填充。使用db.deleteRowByKey(dp);删除行时,您正在更新数据库但未更新dplist

您需要重新填充dplist以匹配数据库,然后才notifyDataSetChanged()按预期工作。

执行此操作的简单方法是将refreshList()功能更改为:

public void refreshList()
{
    //reload dpList so that it can sync up with the database
    dpList = db.allDataThisMonth();

    //now notify adapter that the data set has changed so that it can update itself.
    adapter.notifyDataSetChanged();
}