2015-04-22 130 views
0

这是我的第一个内容提供者, 我被卡住了,因为我无法删除一行。由于我仍然无法使用Junit测试,因此我试图设置内容提供者每次传递一条指令。 我不明白为什么不工作,谢谢内容提供者无法删除SQLite中的行

以方便后续的热点:从FragmentAsList类的方法onContextItemSelected我打电话的ContentResolver的进入提供者类调用合同值和删除的平均值连接到数据库并返回一个int

我也使用CRUD方法附加了数据库类,请注意,在我从ContentResolver执行的删除调用中,有一个getAllRows方法,它连接到Db类,而不是由内容提供者,所以代码可能会出现混淆,但我目前无法使用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); 
    } 

} 

的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; 
    } 
} 

合同类

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); 
     } 
    } 
} 

回答

1

您的ContentProvider类的实现至少在方法delete中是错误的。

你的代码是

@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; 
    } 

但参数的选择不包含表的ROWID。 引述ContentPovider API文档

实施是负责在URI的端解析出一个行ID,如果特定的行要被删除。也就是说,客户端将传入内容:// contacts/people/22,并且实现负责在创建SQL语句时解析记录号(22)。

所以,你应该集中在解析参数URI 建议你读http://developer.android.com/guide/topics/providers/content-provider-basics.html#ContentURIs

特别线

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