内容提供者无法删除 SQLite 中的行
content providers cannot delete row in SQLite
这是我的第一个内容提供商,
我被卡住了,因为我无法删除一行。由于我仍然无法使用 Junit 测试,因此我尝试设置内容提供者每次传递一条指令。
不明白为什么不行,谢谢
为了轻松关注热点:从 FragmentAsList class 在 onContextItemSelected 方法中调用删除,通过 contentResolver 转到提供程序 class 调用 Contracts 值并连接到数据库并返回一个 int
我还使用 CRUD 方法附加了数据库 class,请注意,在我从 ContentResolver 执行的删除调用中,有一个方法 getAllRows 连接到数据库 class 而不是调用由内容提供商提供,因此代码可能看起来很混乱,但我目前无法使用 JUNIT。
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);
}
}
内容提供商
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;
}
}
合同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";
}
}
最后是 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);
}
}
}
您对 class ContentProvider 的实现至少在删除方法中是错误的。
您的密码是
@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;
}
但参数选择不包含 table 的 rowID。
引用 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. 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.
所以你应该专注于解析参数URI
我建议你阅读 http://developer.android.com/guide/topics/providers/content-provider-basics.html#ContentURIs
特别是行
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
这是我的第一个内容提供商, 我被卡住了,因为我无法删除一行。由于我仍然无法使用 Junit 测试,因此我尝试设置内容提供者每次传递一条指令。 不明白为什么不行,谢谢
为了轻松关注热点:从 FragmentAsList class 在 onContextItemSelected 方法中调用删除,通过 contentResolver 转到提供程序 class 调用 Contracts 值并连接到数据库并返回一个 int
我还使用 CRUD 方法附加了数据库 class,请注意,在我从 ContentResolver 执行的删除调用中,有一个方法 getAllRows 连接到数据库 class 而不是调用由内容提供商提供,因此代码可能看起来很混乱,但我目前无法使用 JUNIT。
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);
}
}
内容提供商
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;
}
}
合同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";
}
}
最后是 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);
}
}
}
您对 class ContentProvider 的实现至少在删除方法中是错误的。
您的密码是
@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;
}
但参数选择不包含 table 的 rowID。 引用 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. 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.
所以你应该专注于解析参数URI 我建议你阅读 http://developer.android.com/guide/topics/providers/content-provider-basics.html#ContentURIs
特别是行
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);