【问题标题】:Deleting items from ListView in android从Android中的ListView中删除项目
【发布时间】:2015-08-28 19:22:57
【问题描述】:

从数据库中删除项目后,我无法刷新 ListView。我的应用程序允许您在列表中选择一个条目,该条目会打开一个新活动并根据您单击的项目显示信息(我正在传递列表项 ID),并且该活动中有一个删除按钮。删除时,选择项之前的条目会从 ListView 中删除,选择替换项时信息为空白。

谁能给我一些关于发生了什么的见解?每个人都建议使用notifySetDataChanged(),但这对我不起作用。

这里是 MainActivity:

package com.example.msdproject;

import android.app.ListActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.content.Intent;
import android.widget.ListView;
import android.widget.Button;
import android.widget.ArrayAdapter;
import android.view.View;
import java.sql.SQLException;
import java.util.ArrayList;
import android.util.Log;


public class MainActivity extends ListActivity {

    public ArrayList<String> data_list=new ArrayList<String>();
    DBManager db =  new DBManager(this);
    public ArrayAdapter<String> concertList;


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button add = (Button)findViewById(R.id.addConcertButton);
        add.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(MainActivity.this, AddArtist.class);
                startActivity(i);
            }
        });

        try {
            db.open();
        } catch (SQLException e){
            e.printStackTrace();
        }

        addData();
        //db.close();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        addData();

    }

    public void addData()
    {
        data_list.clear();            
        ListView listView = (ListView) findViewById(android.R.id.list);
        Cursor c = db.getAllConcerts();
        if (c.moveToFirst())
        {
            do {
                data_list.add(c.getString(0));
            } while (c.moveToNext());
        }
        concertList = new ArrayAdapter<String>(getApplicationContext(),
               android.R.layout.simple_list_item_1, data_list);
        listView.setAdapter(concertList);

    }

    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        Intent i =  new Intent(MainActivity.this, ViewArtist.class);
        i.putExtra("id", id);
        startActivity(i);
    }

}

这是 ViewArtist 活动:

package com.example.msdproject;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.sql.SQLException;

public class ViewArtist extends Activity
{

    DBManager db = new DBManager(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_artist);

        Intent intent = getIntent();
        final long num = intent.getLongExtra("id", 1);

        Button update = (Button)findViewById(R.id.updateConcertButton);
        update.setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                Intent i = new Intent(ViewArtist.this, UpdateArtist.class);
                i.putExtra("id", num);
                startActivity(i);
            }
        });

        String name;
        String venue;
        String date;
        String comments;

        try {
            db.open();
            Cursor c = db.getConcert(num + 1);
            //The reason I have num + 1 is because List Item 1 has a ROW_ID of 0
            if (c.moveToFirst())
            {
                do
                {
                    name = (c.getString(1));
                    venue = (c.getString(2));
                    date = (c.getString(3));
                    comments = (c.getString(4));

                    TextView nameTxt = (TextView)findViewById(R.id.viewName);
                    TextView titleTxt = (TextView)findViewById(R.id.viewTitle);
                    TextView venueTxt = (TextView)findViewById(R.id.viewVenue);
                    TextView dateTxt = (TextView)findViewById(R.id.viewDate);
                    TextView commentsTxt = (TextView)findViewById(R.id.viewComments);

                    nameTxt.setText(" " + name);
                    titleTxt.setText("ROW_ID: " + String.valueOf(num));
                    venueTxt.setText(" " + venue);
                    dateTxt.setText(" " + date);
                    commentsTxt.setText(" " + comments);

                    Button del = (Button)findViewById(R.id.deleteConcertButton);
                    del.setOnClickListener(new View.OnClickListener() {

                        @Override
                        public void onClick(View v) {
                            db.deleteConcert(num);
                            Toast.makeText(ViewArtist.this, "Concert Deleted", Toast.LENGTH_LONG).show();

                        }
                    });

                } while (c.moveToNext());
            }
        }

        catch (SQLException e)
        {
            e.printStackTrace();
        }

    }
}

这是包含删除数据库条目代码的 DBManager 类:

package com.example.msdproject;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.content.Context;
import java.sql.SQLException;


public class DBManager {

    public static final String COL_ROWID = "_id";
    public static final String COL_NAME = "name";
    public static final String COL_VENUE = "venue";
    public static final String COL_DATE = "date";
    public static final String COL_COMMENTS = "comments";

    private static final String DB_NAME = "Concerts";
    private static final String DB_TABLE = "Concert_Info";
    private static final int DB_VERSION = 1;

    private static final String DB_CREATE =
            "create table " + DB_TABLE + 
    " (_id integer primary key autoincrement, " +
            "name text not null, " +
            "venue text not null, " +
            "comments text not null, " +
            "date text not null);";

    private final Context context;

    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;

    public DBManager(Context ctx)
    {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }

    //embedded class
    public static class DatabaseHelper extends SQLiteOpenHelper
    {
        //context refers to activity that called it
        DatabaseHelper(Context context)
        {
            super(context, DB_NAME, null, DB_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            db.execSQL(DB_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
            /*
            //taken from YouTube Tutorial video
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("drop table if exists Concert_Info");
            onCreate(db);*/
        }
    }

    public DBManager open() throws SQLException
    {
        db = DBHelper.getWritableDatabase();
        //db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE + ";");
        return this;
    }

    public void close()
    {
        DBHelper.close();
    }

    public long getId(String name)
    {
        long x = 10;
        return x;
    }
    public long insertConcert(String name, String venue, String date, String comments)
    {
        ContentValues initialValues = new ContentValues();
        initialValues.put(COL_NAME, name);
        initialValues.put(COL_VENUE, venue);
        initialValues.put(COL_DATE, date);
        initialValues.put(COL_COMMENTS, comments);
        return db.insert(DB_TABLE, null, initialValues);
    }

    public boolean deleteConcert(long ROW_ID)
    {
        return db.delete(DB_TABLE, COL_ROWID + "=" + ROW_ID, null) > 0;
    }

    public Cursor getAllConcerts() {
        return db.query(DB_TABLE, new String[]
                        {
                                COL_NAME,
                                COL_VENUE,
                                COL_DATE,
                                COL_COMMENTS
                        },
                        null,
                        null,
                        null,
                        null,
                        null
                );
    }

    public Cursor getConcert(long ROW_ID) throws SQLException
    {
        Cursor mCursor =
                db.query(DB_TABLE, new String[]
                        {
                                COL_ROWID,
                                COL_NAME,
                                COL_VENUE,
                                COL_DATE,
                                COL_COMMENTS
                        },
                        COL_ROWID + "=" + ROW_ID,
                        null,
                        null,
                        null,
                        null
                );
        if (mCursor != null)
        {
            mCursor.moveToFirst();
        }

        return mCursor;

    }

    public boolean updateConcert(String name, String venue, String date, String comments)
    {
        ContentValues updateValues = new ContentValues();
        updateValues.put(COL_NAME, name);
        updateValues.put(COL_VENUE, venue);
        updateValues.put(COL_DATE, date);
        updateValues.put(COL_COMMENTS, comments);
        return db.update(DB_TABLE, updateValues, COL_NAME  + "=" + name, null) > 0;
    }

    public void reset () throws SQLException {
        db.delete(DB_TABLE, null, null);
        db.close();
        this.DBHelper.onCreate(this.db);
    }
}

【问题讨论】:

    标签: android database listview


    【解决方案1】:

    将 ListView 与数据库中的一组数据同步可能非常棘手。 基本上,每次您知道数据库中的数据已被修改时,您都需要重新查询它们,用新数据更新适配器,最后调用 onDataSetChanged()。

    我建议你使用CursorAdapter,这是一个适配器,它会自动用游标(例如 SQLiteCursor)的结果填充你的列表。

    【讨论】:

    • 感谢您的回复!如果我切换到使用 CursorAdapter 将 notifyDataSetChanged() 工作?是否有其他方法我必须实施才能获得所需的功能,或者它们会自动工作
    • 感谢您的回答
    【解决方案2】:

    因为您正在查询 COL_ROWID = "_id",

    db.delete(DB_TABLE, COL_ROWID + "=" + ROW_ID, null) > 0;
    

    也就是说,

    _id integer primary key autoincrement,
    

    因此,一旦您删除了该行,它就不显示任何数据(但 _id 存在)。

    您可以做的是,在您的 onListItemClick 中,通过使用字符串查询找到 _id 并将其传递。

    【讨论】:

    • 感谢您的回复!我尝试了你的建议,但我仍然遇到类似的问题。不正确的条目消失了,现在当我选择其他一些条目时,应用程序强制关闭并给我一个超出范围的异常,因为存在越界异常。这是因为它试图选择索引为 0
    • 尝试 { 光标 c = db.getConcert(position);字符串 string_id = c.getString(0); Intent i = new Intent(MainActivity.this, ViewArtist.class); i.putExtra("id", string_id);开始活动(一); } catch (SQLException e) { e.printStackTrace(); }
    • 我之前的建议与您实施的不同。无论如何,另一种解决方案是,在 onListItemClick 内部获取字符串值,如 ConcertList.getItem(position);并传递它而不是 _id 并对您的查询进行更改。
    • 道歉我认为我已经正确地按照你的建议做了。我的新代码是否没有找到 id(位置 0)并将其传递给 viewArtist 活动? viewArtist 活动包含将其转换为 long 的代码
    • 另外需要明确的是,您的第二个解决方案建议是否通过编辑 DBManager.getconcert() 方法以将名称字符串作为参数而不是长 row_id 传递?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 2023-03-18
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    相关资源
    最近更新 更多