简体   繁体   English

内容提供者无法删除SQLite中的行

[英]content providers cannot delete row in SQLite

this is my first content provider, I am stuck because I cannot delete a row. 这是我的第一个内容提供商,因为无法删除行而被困。 Since I am still not able to use Junit tests I am trying to set the content provider passing one instruction per time. 由于我仍然无法使用Junit测试,因此我试图设置内容提供程序每次传递一条指令。 I do not understand why does not work, thank you 我不明白为什么不起作用,谢谢

to easy follow the hot point: from FragmentAsList class in the method onContextItemSelected i call a delete that by mean of a contentResolver goes to the provider class calling the Contracts values and connecting to the DB and returning an int 为了轻松遵循热点:从onContextItemSelected方法的FragmentAsList类中,我调用一个delete,通过contentResolver转到提供者类,该类调用Contracts值并连接到DB并返回一个int

I attach also the DB class with the CRUD methods, please notice that in the delete call I do from ContentResolver there is a method getAllRows that is connected to the Db class instead that called by the Content provider, so the code could appear confuse, but I am not able to use JUNIT at the moment. 我还将DB类与CRUD方法连接在一起,请注意,在从ContentResolver执行的delete调用中,有一个getAllRows方法连接到Db类,而不是由内容提供者调用,因此代码可能会引起混淆,但是我目前无法使用JUNIT。

FragmentAsList FragmentAsList

    package ivano.android.com.ucanote;

import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.format.Time;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import ivano.android.com.ucanote.ivano.android.com.ucanote.db.Db;
import ivano.android.com.ucanote.ivano.android.com.ucanote.db.UcanContentProvider;
import ivano.android.com.ucanote.ivano.android.com.ucanote.db.UcanContract;


/**
* Created by ivano on 3/25/2015.
*/
public class FragmentAsList extends Fragment implements  View.OnCreateContextMenuListener {
    private SimpleCursorAdapter myCursorAdapter;
    private ArrayAdapter<String> mValues;
    //brought out from OnCreateView, have to be in all the class
    List<String> tasks = new ArrayList<String>();

    ListView listView;

    Time today = new Time(Time.getCurrentTimezone());
    Db myDb;
    EditText etTasks;


    public FragmentAsList() {
        super();
    }

public void populateView(){
    Cursor cursor = myDb.getallRows();
    String[] fromFieldNames = new String[]{UcanContract.Tasks._ID,};
    int[] toViewId = new int[]{R.id.text_view};


    //SimpleCursorAdapter myCursorAdapter;

    myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.textview_pretty_cool, cursor, fromFieldNames,
            toViewId, 0);


}
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
        setHasOptionsMenu(true);





//open Database

        myDb = new Db(getActivity());
        myDb.open();


    }


    @Override
    public String toString() {
        return super.toString();
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_fragmentaslist, menu);

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

               // item + " " + item.getItemId());
        switch (id) {
            case R.id.add:

                intent_comunicate.putExtra(getActivity().getPackageName(), "CIao Cipollino");
                startActivityForResult(intent_comunicate, 123);

                break;

        case R.id.delete_all:

            myDb.deleteAll();

            Cursor cursor = myDb.getallRows();
            String[] fromFieldNames = new String[]{UcanContract.Tasks.COLUMN_TASKS};
            int[] toViewId = new int[]{R.id.text_view};


            SimpleCursorAdapter myCursorAdapter;
            myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.textview_pretty_cool, cursor, fromFieldNames, toViewId, 0);
            listView.setAdapter(myCursorAdapter);

        }
        return super.onOptionsItemSelected(item);

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 123) {
            String string = data.getExtras().getString(getActivity().getPackageName());
            Log.d("FragmentAsList", "stringa dall altra activity: " + string);
            Toast.makeText(getActivity(), string, Toast.LENGTH_LONG).show();
            ///database insert
            today.setToNow();
            String timeCurrent = today.format("%Y-%m-%d %H:%M:%S");
            myDb.insertRow(string, timeCurrent, null, null);
            //database query
            Cursor cursor = myDb.getallRows();
            String[] fromFieldNames = new String[]{UcanContract.Tasks.COLUMN_TASKS};
            int[] toViewId = new int[]{R.id.text_view};


            SimpleCursorAdapter myCursorAdapter;
            myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.textview_pretty_cool, cursor, fromFieldNames, toViewId, 0);
            listView.setAdapter(myCursorAdapter);



        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View hiddenList = inflater.inflate(R.layout.fragment_as_list, container, false);

        // Get a reference to the ListView, and attach this adapter to it.
        listView = (ListView) hiddenList.findViewById(R.id.list_hidden);


        registerForContextMenu(listView);
        populateView();
        listView.setAdapter(myCursorAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {



//        Intent explicitIntent =new Intent(getActivity(),DetailNote.class);
//        startActivity(explicitIntent);
            }

        });


        return hiddenList;







    }
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

        super.onCreateContextMenu(menu, v, menuInfo);

        MenuInflater mi = getActivity().getMenuInflater();


        mi.inflate(R.menu.context_menu, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {


        switch (item.getItemId()) {
            case R.id.delete:
                //TODO delete
                registerForContextMenu(listView);
                AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
                int index = info.position;
                String indexToString=Integer.toString(index);
               long b=info.id;

                Uri uri = Uri.parse(UcanContentProvider.CONTENT_URI + "/"
                        + info.id);


                getActivity().getContentResolver().delete(uri, indexToString, null);


                //String indexString = Integer.toString(index);
                Log.d("ivano.android.com.ucanote.FragmentAsList", "onContextItemSelected (line 160): the position is " + index);

//                 myDb.deleteRow(b);
                //database query
                Cursor cursor = myDb.getallRows();
                String[] fromFieldNames = new String[]{UcanContract.Tasks.COLUMN_TASKS};
                int[] toViewId = new int[]{R.id.text_view};
                SimpleCursorAdapter myCursorAdapter;
                myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.textview_pretty_cool, cursor,
                        fromFieldNames, toViewId, 0);
//                SimpleCursorAdapter myCursorAdapter;
//                myCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.textview_pretty_cool, cursor, fromFieldNames, toViewId, 0);
                listView.setAdapter(myCursorAdapter);
                break;
            case R.id.edit:
                break;
            case R.id.share:
                break;

        }

        return super.onContextItemSelected(item);
    }

}

ContentProvider 内容提供商

package ivano.android.com.ucanote.ivano.android.com.ucanote.db;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;


public class UcanContentProvider extends ContentProvider {

    public Db.DatabaseHelper myDBHelper;
    public static final String AUTHORITY = "ivano.android.com.ucanote.db.UcanContentProvider";

    public static final String PATH_TASKS="tasks";



    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
    public static final Uri CONTENT_URI =BASE_CONTENT_URI.buildUpon().appendPath(PATH_TASKS).build();



    @Override
    public boolean onCreate() {
        //TODO not sure i need it see Android for busy programmers page 979, I have it already as constructor in Db.java that has the Helper
        //as inner class
        myDBHelper = new Db.DatabaseHelper(getContext());


        return false;
    }
//
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        //Using SQLiteQueryBuilder instead of query() method
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(UcanContract.Tasks.DATABASE_TABLE);

        Cursor cursor = qb.query(myDBHelper.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder);
        cursor.setNotificationUri(getContext().getContentResolver(), uri);


        return cursor;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {

        int count = myDBHelper.getWritableDatabase().delete(UcanContract.Tasks.DATABASE_TABLE,
                UcanContract.Tasks._ID + " = " + selection, selectionArgs);
        getContext().getContentResolver().notifyChange(uri, null);

        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

Contract class 合同类别

package ivano.android.com.ucanote.ivano.android.com.ucanote.db;

import android.provider.BaseColumns;

public  class UcanContract{





public static final class  Tasks implements BaseColumns{


    public static final String COLUMN_TASKS = "task";
    public static final String COLUMN_DATE = "date";
    public static final String COLUMN_URGENCY = "urgency";
    public static final String COLUMN_TAG = "tag";




    public static final String[] ALL_ROWS=new String[]{_ID, COLUMN_TASKS, COLUMN_DATE, COLUMN_URGENCY, COLUMN_TAG};
 public static final String DATABASE_TABLE="table1";
}


}

and finally DB 最后是DB

package ivano.android.com.ucanote.ivano.android.com.ucanote.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Created by ivano on 4/8/2015.
 */
public class Db {
    private static final String TAG="Db";
//TODO check if all the fields are used,
// expecially TAG, ALL KEYS and columns, and what is the function of DB info?

    //fields


    //DB info
    public static final String DATABASE_NAME = "db";

    //always remember to change this if I are going to update the DB!
    public static final int    DATABASE_VERSION=1;

    //create

    private static final String DATABASE_CREATE_SQL=
            "CREATE TABLE " + UcanContract.Tasks.DATABASE_TABLE
            + " ("  + UcanContract.Tasks._ID+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + UcanContract.Tasks.COLUMN_TASKS + " TEXT NOT NULL, "
            + UcanContract.Tasks.COLUMN_DATE + " TEXT, "
            + UcanContract.Tasks.COLUMN_URGENCY +" TEXT, "
            + UcanContract.Tasks.COLUMN_TAG +" TEXT " +
                    " );";


private final Context context;
    public DatabaseHelper myDBHelper;
    private SQLiteDatabase db;

public Db (Context ctx) {
    this.context = ctx;
    myDBHelper=new DatabaseHelper(context);
    }

    public Db open() {
    db= myDBHelper.getWritableDatabase();
        return this;
    }

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

    public long insertRow (String task,String date, String urgency, String tag) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(UcanContract.Tasks.COLUMN_TASKS, task);
        initialValues.put(UcanContract.Tasks.COLUMN_DATE, date);
        initialValues.put(UcanContract.Tasks.COLUMN_URGENCY, urgency);
        initialValues.put(UcanContract.Tasks.COLUMN_TAG, tag);

    return db.insert(UcanContract.Tasks.DATABASE_TABLE,null,initialValues);
    }
        //delete a row from the db by _id
        public boolean deleteRow(long rowId) {
            String where = UcanContract.Tasks._ID + "=" + rowId;


              //db.delete(DATABASE_TABLE, where, null) ;
             return db.delete(UcanContract.Tasks.DATABASE_TABLE, where, null) != 0;
        }




    public void deleteAll(){
        Cursor c=getallRows();
        long rowId=c.getColumnIndex(UcanContract.Tasks._ID);
        if (c.moveToFirst()) {
            do {
                deleteRow(c.getLong((int) rowId));

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

    }
    public Cursor getallRows(){
        String where=null;
        Cursor c=db.query(true, UcanContract.Tasks.DATABASE_TABLE, UcanContract.Tasks.ALL_ROWS,where,null,null,null,null,null);
   if (c!= null){
c.moveToFirst();
    }
      return c;


    }
public Cursor getRow(long rowId){
    String where =UcanContract.Tasks._ID+"=" +rowId;
    Cursor c=db.query(true, UcanContract.Tasks.DATABASE_TABLE, UcanContract.Tasks.ALL_ROWS,where,null,null,null,null,null);
    if(c!= null){
        c.moveToFirst();
    }
    return c;

}
    public boolean updateRow(long rowId,String task,String date, String urgency,String tag){
        String where =UcanContract.Tasks._ID+"="+rowId;
        ContentValues newValues =new ContentValues();
        newValues.put(UcanContract.Tasks.COLUMN_TASKS,task);

        newValues.put(UcanContract.Tasks.COLUMN_DATE, date);
        newValues.put(UcanContract.Tasks.COLUMN_URGENCY, urgency);
        newValues.put(UcanContract.Tasks.COLUMN_TAG, tag);
        return db.update(UcanContract.Tasks.DATABASE_TABLE,newValues,where,null)!=0;

    }

    public static class DatabaseHelper extends SQLiteOpenHelper{
        DatabaseHelper(Context context){
            super (context,DATABASE_NAME,null,DATABASE_VERSION);

        }

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

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG,"Upgrading application's database from version"
                    +oldVersion+ " to "+newVersion+
                    " ,which will destroy all the old data!");
            db.execSQL("DROP TABLE IF EXISTS "+ UcanContract.Tasks.DATABASE_TABLE);
            onCreate(db);
        }
    }
}

Your implementation of the class ContentProvider is wrong at least in the method delete. 至少在方法delete中,您对ContentProvider类的实现是错误的。

your code is 你的代码是

@Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {

        int count = myDBHelper.getWritableDatabase().delete(UcanContract.Tasks.DATABASE_TABLE,
                UcanContract.Tasks._ID + " = " + selection, selectionArgs);
        getContext().getContentResolver().notifyChange(uri, null);

        return count;
    }

but the parameter selection doesn't contain the rowID of the table. 但参数选择不包含表的rowID。 Quoting the ContentPovider api doc 引用ContentPovider API文档

The implementation is responsible for parsing out a row ID at the end of the URI, if a specific row is being deleted. 如果要删除特定行,该实现负责解析URI末尾的行ID。 That is, the client would pass in content://contacts/people/22 and the implementation is responsible for parsing the record number (22) when creating a SQL statement. 也就是说,客户端将传入content:// contacts / people / 22,并且实现负责创建SQL语句时解析记录号(22)。

So you should focus on parsing the parameter URI I suggest you to read http://developer.android.com/guide/topics/providers/content-provider-basics.html#ContentURIs 因此,您应该专注于解析参数URI,建议您阅读http://developer.android.com/guide/topics/providers/content-provider-basics.html#ContentURIs

Especially line 特别是线

Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4); Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM