可以使用按钮删除从项目添加的数据库条目吗? [英] Can database entries added from items be deleted with button?

查看:82
本文介绍了可以使用按钮删除从项目添加的数据库条目吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用"Android编程:大书呆子牧场指南"自学android开发,其中一项练习(如果您熟悉这本书,请参阅第14章)涉及创建一个工具栏,其中的一项会添加新内容单击该项目时进入数据库的条目.一个挑战性的问题是删除条目,但我想从WITHIN条目中删除条目.抱歉,如果我没有做好解释.

I'm trying to teach myself android development using "Android Programming: The Big Nerd Ranch Guide" and one of the exercises (from chapter 14 if you are familiar with the book) involves creating a toolbar with an item that adds new entries to the database when the item is clicked. A challenge question is deleting the entries, but I want to delete the entry from WITHIN the entry. Sorry if I am not doing a good job explaining this.

基本上是首次打开该应用程序时,在右上角有两个工具栏的工具栏几乎是空的. 如果有帮助,请看这里的屏幕截图.这两个项目相加或计数的条目数,然后将其显示在列表上.在上图中,只有一个条目.当您单击+符号时,将添加一个新条目,它将带您进入布局您可以添加所有详细信息的条目.我想添加一个删除按钮,使您可以在查看详细信息时删除条目.

Basically when opening the app for the first time, there is a mostly empty display with a toolbar with two items in the top right. Here is a screenshot if it helps. The two items add or count the number of entries, which are then displayed on the list. In the image above, there is one entry. When you click the + symbol, a new entry is added, and it takes you to the layout for the entry that lets you add all the details. I want to add a delete button that allows you to erase the entry while looking at the details.

这是我尝试但无法正常工作的代码: 在CrimeLab.java

Here is the code I tried but didn't work: In CrimeLab.java

public void addCrime(Crime c){
    ContentValues values = getContentValues(c);

    mDatabase.insert(CrimeTable.NAME, null, values);
}

public void deleteCrime(Crime crimeId){

    String uuidString = crimeId.toString();
    mDatabase.delete(CrimeTable.NAME, null, new String[] 
{uuidString});
}

我基本上试图撤消创建数据库条目时的操作. 在CrimeListFragment.java中:

I basically tried to undo what I did when creating a database entry. In CrimeListFragment.java:

@Override
public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()){
        case R.id.menu_item_new_crime:
            Crime crime = new Crime();
            CrimeLab.get(getActivity()).addCrime(crime);
            Intent intent = 
CrimePagerActivity.newIntent(getActivity(), crime.getId());
            startActivity(intent);
            return true;
        case R.id.menu_item_show_subtitle:
            mSubtitleVisible = !mSubtitleVisible;
            getActivity().invalidateOptionsMenu();
            updateSubtitle();
            return true;
        case R.id.delete_button:
            Crime mCrime = new Crime();
            CrimeLab.get(getActivity()).deleteCrime(mCrime);
        default:
            return super.onOptionsItemSelected(item);
    }
}

我认为我需要创建一个onClick动作,但是如果我试图从由条目中的项创建的数据库中删除条目,该怎么办?

I think I need to create an onClick action, but where would this go if I'm trying to delete entries from a database created by items from within the entry?

我想添加的其他功能是通过滑动以显示删除按钮来从原始页面删除条目,就像在Messenger应用中一样.

Something else I would like to add is deleting entries from the original page by sliding to reveal a delete button, like in messenger apps.

抱歉,如果我没有正确提出问题.对我来说,这是一个全新的世界,与本书一起阅读是很有帮助的,但是我发现它很容易使您认为您理解了某些内容,然后完全迷失了自己. 另外,我检查了stackoverflow和其他各种论坛,但没有找到这个问题的确切答案.

Sorry if I didn't properly ask my question. This is a whole new world for me and going along with the book is helpful, but I found its easy to think you understand something and then be completely lost on your own. Also, I checked though stackoverflow and other various forums and did not find an exact answer to this question.

每个请求,这是Crime.java的代码:

Per request, here is the code for Crime.java:

public class Crime {
    private String mTitle;
    private Date mDate;
    private boolean mSolved;
    private String mSuspect;

    public Date getDate() {
        return mDate;
    }

    private UUID mId;

    public void setDate(Date date) {
        mDate = date;
    }

    public void setSolved(boolean solved) {
        mSolved = solved;
    }

    public String getSuspect(){
        return mSuspect;
    }

    public  void setSuspect (String suspect){
        mSuspect = suspect;
    }

    public String getPhotoFilename(){
        return "IMG_" + getId().toString() + ".jpg";
    }

    public boolean isSolved() {

        return mSolved;
    }



    public Crime(){
        //generate unique identifier
        this(UUID.randomUUID());
    }

    public Crime(UUID id){
        mId = id;
        mDate = new Date();
    }

    public UUID getId() {
        return mId;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }
}

这是控制我的数据库条目的.java类:

This is the .java class that controls my database entries:

public class CrimeBaseHelper extends SQLiteOpenHelper{
    private static final int VERSION = 1;
    private static final String DATABASE_NAME = "crimeBase.db";

    public CrimeBaseHelper(Context context){
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db){
        db.execSQL("create table " + CrimeTable.NAME + "(" +
                " _id integer primary key autoincrement, " +
                CrimeTable.Cols.UUID + ", " +
                CrimeTable.Cols.TITLE + ", " +
                CrimeTable.Cols.DATE + ", " +
                CrimeTable.Cols.SOLVED + ", " +
                CrimeTable.Cols.SUSPECT +
                ")"
        );

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){

    }
}

这是我搞砸.onClickListener

This is where I am messing up the .onClickListener

mDeleteButton = (Button)v.findViewById(R.id.delete_button);
        mDeleteButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                Crime mCrime = new crime();
                mCrime.getId()
                CrimeLab.get(getActivity()).deleteCrime(mCrime);
            }
                                         }
        );

推荐答案

替代答案

以下是一个非常基本但有效的示例的代码.但是,通过合并 ListView 并允许通过长按 ListView 中的项目来允许删除,可以进行进一步操作.

Alternative Answer

The following is the code for a pretty basic, but working example. However, it goes a little further by incorporating a ListView and allowing deletion by LongClicking an item in the ListView.

但是,这不使用片段.

有3段代码, MainActivity (MainActivity.java),SQLiteOpenHelper子类 CrimeDBHelper (CrimeDBHelper.java)和MainActivity的布局,activity_main.xml :-

There's 3 pieces of code, the MainActivity (MainActivity.java), The SQLiteOpenHelper subclass CrimeDBHelper (CrimeDBHelper.java) and the layout for the MainActivity, activity_main.xml:-

这很简单.请注意,它的末尾包含一个 ListView .

This is pretty straight-forward. Note that it includes a ListView at the end.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="The Crime Thing"
    android:layout_gravity="center"
    android:textStyle="bold"/>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="Crime Title"
        />
    <EditText
        android:id="@+id/crimetitle"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="Crime Date"
        />
    <EditText
        android:id="@+id/crimedate"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="Suspect"
        />
    <EditText
        android:id="@+id/crimesuspect"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="Crime Solved?"
        />
    <CheckBox
        android:id="@+id/crimesolved"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content" />
</LinearLayout>
<Button
    android:id="@+id/addcrime"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="ADD CRIME"/>
<Button
    android:id="@+id/dltcrime"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="DLT CRIME (ID=?)"/>
<ListView
    android:id="@+id/crimelist"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
</ListView>

除其他方法 getCrimeList() 外,其他大部分相似,这将返回一个Cursor,其中包含criminions表中的所有数据(用于填充ListView).

Most is similar, except the additional method getCrimeList(), this returns a Cursor that contains all the data from the crimes table (used for populating the ListView).

public class CrimeDBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "crimesdb";
    public static final int DBVERSION = 1;
    public static final String CRIMESTABLE = "crimes";
    public static final String CRIMEID_COL = "_id";
    public static final String CRIMETITLE_COL = "crimetitle";
    public static final String CRIMEDATE_COL = "crimedate";
    public static final String CRIMESUSPECT_COL = "crimesuspect";
    public static final String CRIMESOLVED_COL = "crimesolved";


    public static final String TABLECRTSQL =
            "CREATE TABLE " + CRIMESTABLE + "(" +
                    CRIMEID_COL + " INTEGER PRIMARY KEY," +
                    CRIMETITLE_COL + " TEXT," +
                    CRIMEDATE_COL + " TEXT, " +
                    CRIMESUSPECT_COL + " TEXT, " +
                    CRIMESOLVED_COL + " INTEGER" +
                    ");";

    public CrimeDBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

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

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {
    }

    public long addCrime(String crimetitle, String crimedate, String crimesuspect, int crimesolved) {

        SQLiteDatabase db = getWritableDatabase();

        ContentValues cv = new ContentValues();
        cv.put(CRIMETITLE_COL,crimetitle);
        cv.put(CRIMEDATE_COL,crimedate);
        cv.put(CRIMESUSPECT_COL,crimesuspect);
        cv.put(CRIMESOLVED_COL,crimesolved);
        return db.insert(CRIMESTABLE,null,cv);
    }

    public int deleteCrime(long crimeid) {
        SQLiteDatabase db = getWritableDatabase();
        String whereclause = CRIMEID_COL + "=?";
        String[] whereargs = {Long.toString(crimeid)};
        return db.delete(CRIMESTABLE,whereclause,whereargs);
    }

    public Cursor getCrimeList() {
        SQLiteDatabase db = getWritableDatabase();
        return db.query(CRIMESTABLE,null,null,null,null,null,null,null);
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    EditText mCrimeTitle;
    EditText mCrimeDate;
    EditText mCrimeSuspect;
    CheckBox mCrimeSolved;

    Button mAddCrime;
    Button mDltCrime;
    ListView mCrimeList;

    CrimeDBHelper dbhlpr = new CrimeDBHelper(this);
    Cursor crimelist;
    SimpleCursorAdapter sca;

    long lastcrimeid;

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

        mCrimeTitle = (EditText) findViewById(R.id.crimetitle);
        mCrimeDate = (EditText) findViewById(R.id.crimedate);
        mCrimeSuspect = (EditText) findViewById(R.id.crimesuspect);
        mCrimeSolved = (CheckBox) findViewById(R.id.crimesolved);
        mCrimeList = (ListView) findViewById(R.id.crimelist);
        mAddCrime = (Button) findViewById(R.id.addcrime);
        mDltCrime = (Button) findViewById(R.id.dltcrime);

        crimelist = dbhlpr.getCrimeList();

        // Setup Button to Add a crime
        mAddCrime.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int solved = 0;
                if (mCrimeSolved.isChecked()) {
                    solved = 1;
                }
                lastcrimeid =  dbhlpr.addCrime(
                        mCrimeTitle.getText().toString(),
                        mCrimeDate.getText().toString(),
                        mCrimeSuspect.getText().toString(),
                        solved
                );
                mDltCrime.setText("DLT CRIME (ID=" + Long.toString(lastcrimeid) + ")");
                mDltCrime.setTag(lastcrimeid);
                crimelist = dbhlpr.getCrimeList();
                sca.swapCursor(crimelist);
            }
        });

        // Setup button to delete the latest Crime added
        mDltCrime.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //dbhlpr.deleteCrime(lastcrimeid); can do it this way
                if (view.getTag() != null) {
                    dbhlpr.deleteCrime((long)view.getTag());
                    crimelist = dbhlpr.getCrimeList();
                    sca.swapCursor(crimelist);
                }
            }
        });

        sca = new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1,
                crimelist,
                new String[]{CrimeDBHelper.CRIMETITLE_COL},
                new int[]{android.R.id.text1},
                0
        );
        mCrimeList.setAdapter(sca);

        mCrimeList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
                dbhlpr.deleteCrime(l);
                crimelist = dbhlpr.getCrimeList();
                sca.swapCursor(crimelist);
                return true;
            }
        });

    }

    protected void onDestroy() {
        super.onDestroy();
        if (crimelist != null) {
            crimelist.close();
        }

    }
}

首先要注意的是long lastcrimeid;行,它是在类级别上声明的,因此在整个过程中都非常有用( long databaseID 遇到的问题).

The first thing to note is the line long lastcrimeid;, this is declared at the class level so is very much available throughout (the issue you were having with long databaseID).

您可能还会注意到 SimpleCursorAdapter sca; ,这将用于 ListView (基本上是将光标中的数据放置在ListView中).

You might also notice SimpleCursorAdapter sca; this will be used for the ListView (basically it places the data from the cursor in the ListView).

您应该熟悉以下许多代码.总结:-

You should be familiar with much of the following code. In summray:-

  • super.onCreate被调用.
  • 该活动设置为使用activity_main.xml布局.
  • 在加载布局后,将获得与视图关联的id.
  • 获得了一个Cursor,可以从数据库中获取当前的犯罪信息(可能没有,这不是问题).

  • super.onCreate is called.
  • The activity is set to use the activity_main.xml layout.
  • As the layout has been loaded the id's associated with the views are obtained.
  • A Cursor is obtained getting the current crimes from the database (may be none, this isn't a problem).

添加了用于添加犯罪的按钮侦听器.请注意,这两次使用返回的添加行的 _id (实际上是3次,因为它相应地更改了删除按钮的文本).

the button listener for adding a crime is added. Note that this uses the returned _id of the added row twice (actually 3 times as it changes the delete buttons text accordingly).

  • lastcrimeid 是通过addCrime()方法的返回设置的.
  • mDltCrime.setTag(lastcrimeid);将删除按钮的标签设置为添加行的 _id .

  • lastcrimeid is set by the return of the addCrime() method.
  • mDltCrime.setTag(lastcrimeid); sets the tag of the delete button to the _id of the added row.

还要注意,还存在另外两个行,分别是crimelist = dbhlpr.getCrimeList();sca.swapCursor(crimelist);.

Also note that two additional lines exist namely crimelist = dbhlpr.getCrimeList(); and sca.swapCursor(crimelist);.

  • 第一个将光标替换为数据库中现在的内容(即包括已添加的行),第二个告诉ListView使用新的光标,因此使ListView显示数据库中的现在内容(删除行时会再次使用.)

然后添加删除按钮的按钮侦听器.这可以通过两种方式进行.可以使用 lastcrimeid ,也可以使用按钮的有效期,因为它们都保留了要删除的行的 _id .该代码已将前者注释掉,因此使用后一种方法(即检索按钮标签中的值).

the button listener for the delete button is then added. This can work in two ways. The lastcrimeid can be used or alternately the button's tage can be used as both hold the _id of the row to be deleted. The code has the former commented out, so the latter method is used (i.e. the value in the button's tag is retrieved).

  • 请注意,后一种方法的缺点是该值可以为null,这将导致null指针异常,因此if (view.getTag != null).

如上所述,用于刷新 ListView .

接下来,设置SimpleCursorAdapter,它需要5个参数:-

Next the SimpleCursorAdapter is setup, it takes 5 parameters:-

  • 要使用的布局(android.R.layout.simple_list_item_1)是库存布局.
  • 要以游标形式使用的数据.笔记!必须存在一个名为 _id 的列(出于这个原因,通常总是使用_id INTEGER PRIMARY KEY是一个好主意..)请注意,我们得到了一个光标 crimelist >通过getCrimeList方法.
  • 光标中要从中检索数据的列.
  • 将在其中放置检索到的数据的布局中的视图.
  • 一个我不记得其目的的值.但是,0可以使用.不对此第5个参数进行编码可能会导致不推荐使用的消息.
  • (请注意,我通常使用Custom CursorAdapters,因为它们更加灵活,因此很少使用Simples.)
  • the layout to be used (android.R.layout.simple_list_item_1) is a stock layout.
  • the data to be used in the form of a Cursor. NOTE! a column named _id MUST exist (generally a good idea to always use _id INTEGER PRIMARY KEY for this reason.) Note we get a Cursor crimelist via the getCrimeList method.
  • The column(s) in the cursor from which the data is to be retrieved.
  • The view(s) in the layout where the retrieved data will be placed.
  • A value which I can't recall the purpose of. However 0 is fine to use. Not coding this 5th parameter will likely result in deprecated message.
  • (Note I normally use Custom CursorAdapters as they are much more flexible, so rarely use Simples).

然后告诉ListView按照mCrimeList.setAdapter(sca);使用适配器.

Then the ListView is told to use the Adapter as per mCrimeList.setAdapter(sca);.

然后将一个onItemLongClickListener添加到ListView,它将删除长按的罪行(长l是 _id 的值,因此是CursorAdapter需要的原因_id ,因此为什么要使用dbhlpr.deleteCrime(l);.

Then an onItemLongClickListener is added to the ListView, which will delete the crime that was longclicked (long l is the _id value, hence a reason why a CursorAdapter needs _id and hence why dbhlpr.deleteCrime(l);).

  • 再次刷新 ListView .

最后,因为在活动保持使用状态时使用了光标,所以onDestory方法用于关闭游标(完成后应始终关闭游标).

Finally, as the cursor is used while the activity remains in use onDestory method is used to close the Cursor (Cursors should always be closed when finished with).

这是它的外观(不漂亮,但很实用),添加了三个犯罪(删除按钮将删除世纪犯罪犯罪).长按任何列出的犯罪将删除该犯罪.除非更改数据,否则单击添加将为世纪罪行"添加另一个条目.

This is how it looks (not pretty but functional), with three Crimes added (The delete button would remove the The Crime of the Century crime). Long-Clicking any listed crime will delete that crime. Clicking add would add another entry for Crime of the Century unless the data were changed.

这篇关于可以使用按钮删除从项目添加的数据库条目吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆