ContentProvider с несколькими таблицами, все виды ошибок
Я создал один ContentProvider в качестве внешнего интерфейса для моих 3 таблиц sqlitedb. Это мой первый ContentProvider, и я не могу найти хорошее руководство по его созданию. Схема на самом деле очень проста.
ОРГАНЫ УПРАВЛЕНИЯ: _id, заголовок, текст, последний (время) использования, номер телефона
СОБЫТИЯ: _id, текст, номер телефона, дата, тип
NUMBERS: _id, title, phoneNumber
Есть несколько видов ошибок, на данный момент моя самая большая проблема:
1) У меня есть две вкладки со списком фрагментов, вкладка 1 загружает элементы управления, вкладка 2 загружает события. Tab1 будет загружаться вечно (используя LOADER, чтобы сделать его асинхронной), Tab2 будет отображать пустое сообщение через 1 секунду (работает как задумано).
2) Когда я пытаюсь вставить что-то в таблицу NUMBERS, я получаю приведенный ниже logcat (ДОЛЖЕН РЕДАКТИРОВАТЬ ИЗ-ЗА ПРЕДЕЛ CHAR), который говорит, что столбцы не существуют. (Я тестировал вставку в другие таблицы, но я думаю, что результат тот же) Метод ContentResolver.insert даст -1 в результате.
3) когда я строю запрос, я обычно использую:
String selection = MyContentProvider.Data.C_ID + "=";
String[] args = {+ String.valueOf(id)};
в качестве selection и selectionArgs для запроса. С этим ContentProvider я должен использовать:
String selection = MyContentProvider.Data.C_ID + "='" + String.valueOf(id) + "'";
как выбор и нуль как selectionArgs или я получаю синтаксическую ошибку.
Это происходит, когда я вызываю этот метод:
public void save(){
name= etContactName.getText().toString();
number= etPhoneNumber.getText().toString();
String empty="";
if(name.equals(null) || number.equals(null) || name.equals(empty) || number.equals(empty)){
Toast.makeText(this, "Enter both name and number", Toast.LENGTH_SHORT).show();
}else{
ContentResolver cr= this.getContentResolver();
ContentValues values= new ContentValues();
values.put(MyContentProvider.Data.N_TITLE, name);
values.put(MyContentProvider.Data.N_NUMBER, number);
cr.insert(MyContentProvider.Data.CONTENT_URI_NUMBERS, values);
NavUtils.navigateUpFromSameTask(this);
}
}
И последнее, но не менее важное, весь мой класс MyContentProvider, где, как мне кажется, лежит ошибка:
public class MyContentProvider extends ContentProvider {
@SuppressWarnings("unused")
private static final String TAG = "SurvContentProvider";
private static final String DATABASE_NAME = "surv.db";
private static final int DATABASE_VERSION = 5;
public static class Data{
private Data(){
}
//Content Types
public static final String CONTENT_TYPE_EVENTS =
"vnd.android.cursor.dir/vnd.com.corsalini.survcontr.SurvContentProvider.EVENTS";
public static final String CONTENT_TYPE_EVENTS_ID =
"vnd.android.cursor.item/vnd.com.corsalini.survcontr.SurvContentProvider.EVENTS";
public static final String CONTENT_TYPE_CONTROLS =
"vnd.android.cursor.dir/vnd.com.corsalini.survcontr.SurvContentProvider.CONTROLS";
public static final String CONTENT_TYPE_CONTROLS_ID =
"vnd.android.cursor.item/vnd.com.corsalini.survcontr.SurvContentProvider.CONTROLS";
public static final String CONTENT_TYPE_NUMBERS =
"vnd.android.cursor.dir/vnd.com.corsalini.survcontr.SurvContentProvider.NUMBERS";
public static final String CONTENT_TYPE_NUMBERS_ID =
"vnd.android.cursor.item/vnd.com.corsalini.survcontr.SurvContentProvider.NUMBERS";
//Content URIs
public static final Uri CONTENT_URI_EVENTS = Uri.parse("content://"
+ MyContentProvider.AUTHORITY + "/EVENTS");
public static final Uri CONTENT_URI_CONTROLS = Uri.parse("content://"
+ MyContentProvider.AUTHORITY + "/CONTROLS");
public static final Uri CONTENT_URI_NUMBERS = Uri.parse("content://"
+ MyContentProvider.AUTHORITY + "/NUMBERS");
//Tables
//EVENTS Table
public static final String E_ID= "_id";
public static final String E_TEXT= "ETEXT";
public static final String E_NUMBER= "ENUMBER";
public static final String E_TYPE= "ETYPE";
public static final String E_DATE= "EDATE";
//Type COSTANTS
public static final int SENT_PROGRESS=0;
public static final int SENT_COMPLETED=1;
public static final int RECEIVED_UNREAD=2;
public static final int RECEIVED_READ=3;
//CONTROLS Table
public static final String C_ID= "_id";
public static final String C_TITLE= "CTITLE";
public static final String C_TEXT= "CTEXT";
public static final String C_LAST= "CLAST";
public static final String C_NUMBER= "CNUMBER";
//NUMBERS Table
public static final String N_ID= "_id";
public static final String N_TITLE= "NTITLE";
public static final String N_NUMBER= "NNUMBER";
}
private static HashMap<String, String> eventsProjectionMap;
private static HashMap<String, String> controlsProjectionMap;
private static HashMap<String, String> numbersProjectionMap;
public static final String AUTHORITY = "com.corsalini.survcontr.SurvContentProvider";
private static final int EVENTS=1;
private static final int EVENTS_ID=10;
private static final int CONTROLS=2;
private static final int CONTROLS_ID=20;
private static final int NUMBERS=3;
private static final int NUMBERS_ID=30;
private static final String TABLE_NAME_EVENTS = "EVENTS";
private static final String TABLE_NAME_CONTROLS = "CONTROLS";
private static final String TABLE_NAME_NUMBERS = "NUMBERS";
public static final String CREATE_TABLE_EVENTS= "CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME_EVENTS + " ("
+ Data.E_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ Data.E_TEXT + " TEXT NULL, "
+ Data.E_NUMBER + " TEXT NULL, "
+ Data.E_TYPE + " INTEGER NULL, "
+ Data.E_DATE + " TEXT NULL);";
public static final String CREATE_TABLE_CONTROLS= "CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME_CONTROLS + " ("
+ Data.C_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ Data.C_TITLE + " TEXT NULL, "
+ Data.C_TEXT + " TEXT NULL, "
+ Data.C_NUMBER + " TEXT NULL, "
+ Data.C_LAST + " TEXT NULL);";
public static final String CREATE_TABLE_NUMBERS= "CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME_NUMBERS + " ("
+ Data.N_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ Data.N_TITLE + " TEXT NULL, "
+ Data.N_NUMBER + " INTEGER NULL);";
private static final UriMatcher sUriMatcher;
static{
//UriMatcher
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, "EVENTS", EVENTS);
sUriMatcher.addURI(AUTHORITY, "EVENTS/#", EVENTS_ID);
sUriMatcher.addURI(AUTHORITY, "CONTROLS", CONTROLS);
sUriMatcher.addURI(AUTHORITY, "CONTROLS/#", CONTROLS_ID);
sUriMatcher.addURI(AUTHORITY, "NUMBERS", NUMBERS);
sUriMatcher.addURI(AUTHORITY, "NUMBERS/#", NUMBERS_ID);
//eventsProjectionMap
eventsProjectionMap = new HashMap<String, String>();
eventsProjectionMap.put(Data.E_ID, Data.E_ID);
eventsProjectionMap.put(Data.E_TEXT, Data.E_TEXT);
eventsProjectionMap.put(Data.E_NUMBER, Data.E_NUMBER);
eventsProjectionMap.put(Data.E_TYPE, Data.E_TYPE);
eventsProjectionMap.put(Data.E_DATE, Data.E_DATE);
//controlsProjectionMap
controlsProjectionMap = new HashMap<String, String>();
controlsProjectionMap.put(Data.C_ID, Data.C_ID);
controlsProjectionMap.put(Data.C_TITLE, Data.C_TITLE);
controlsProjectionMap.put(Data.C_TEXT, Data.C_TEXT);
controlsProjectionMap.put(Data.C_LAST, Data.C_LAST);
controlsProjectionMap.put(Data.C_NUMBER, Data.C_NUMBER);
//numbersProjectionMap
numbersProjectionMap = new HashMap<String, String>();
numbersProjectionMap.put(Data.N_ID, Data.N_ID);
numbersProjectionMap.put(Data.N_TITLE, Data.N_TITLE);
numbersProjectionMap.put(Data.N_NUMBER, Data.N_NUMBER);
}
private DatabaseHelper dbHelper;
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_EVENTS);
db.execSQL(CREATE_TABLE_CONTROLS);
db.execSQL(CREATE_TABLE_NUMBERS);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_EVENTS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_CONTROLS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_NUMBERS);
db.execSQL(CREATE_TABLE_EVENTS);
db.execSQL(CREATE_TABLE_CONTROLS);
db.execSQL(CREATE_TABLE_NUMBERS);
}
}
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count=0;
switch (sUriMatcher.match(uri)) {
case EVENTS:
break;
case EVENTS_ID:
where = where + "_id = " + uri.getLastPathSegment();
count = db.delete(TABLE_NAME_EVENTS, where, whereArgs);
break;
case CONTROLS:
break;
case CONTROLS_ID:
where = where + "_id = " + uri.getLastPathSegment();
count = db.delete(TABLE_NAME_CONTROLS, where, whereArgs);
break;
case NUMBERS:
break;
case NUMBERS_ID:
where = where + "_id = " + uri.getLastPathSegment();
count = db.delete(TABLE_NAME_NUMBERS, where, whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case EVENTS:
return Data.CONTENT_TYPE_EVENTS;
case EVENTS_ID:
return Data.CONTENT_TYPE_EVENTS_ID;
case CONTROLS:
return Data.CONTENT_TYPE_CONTROLS;
case CONTROLS_ID:
return Data.CONTENT_TYPE_CONTROLS_ID;
case NUMBERS:
return Data.CONTENT_TYPE_NUMBERS;
case NUMBERS_ID:
return Data.CONTENT_TYPE_NUMBERS_ID;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
if (sUriMatcher.match(uri) != EVENTS && sUriMatcher.match(uri) != CONTROLS
&& sUriMatcher.match(uri) != NUMBERS) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
else
{
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
long rowId=0;
switch (sUriMatcher.match(uri)) {
case EVENTS:
rowId = db.insert(TABLE_NAME_EVENTS, Data.E_TEXT, values);
break;
case CONTROLS:
rowId = db.insert(TABLE_NAME_CONTROLS, Data.C_TEXT, values);
break;
case NUMBERS:
rowId = db.insert(TABLE_NAME_EVENTS, Data.N_TITLE, values);
break;
}
Log.d("INSERT", "ROWID= "+rowId);
if (rowId > 0) {
Log.d("INSERT", "ROWID= "+rowId +" ENTRATO");
Uri noteUri=null;
switch (sUriMatcher.match(uri)) {
case EVENTS:
noteUri = ContentUris.withAppendedId(Data.CONTENT_URI_EVENTS, rowId);
break;
case CONTROLS:
noteUri = ContentUris.withAppendedId(Data.CONTENT_URI_CONTROLS, rowId);
break;
case NUMBERS:
noteUri = ContentUris.withAppendedId(Data.CONTENT_URI_NUMBERS, rowId);
break;
}
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}else{
throw new SQLException("Failed to insert row into " + uri);
}
}
}
@Override
public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (sUriMatcher.match(uri)) {
case EVENTS:
qb.setTables(TABLE_NAME_EVENTS);
qb.setProjectionMap(eventsProjectionMap);
break;
case EVENTS_ID:
qb.setTables(TABLE_NAME_EVENTS);
qb.setProjectionMap(eventsProjectionMap);
selection = selection + "_id =?s " + uri.getLastPathSegment();
break;
case CONTROLS:
qb.setTables(TABLE_NAME_CONTROLS);
qb.setProjectionMap(controlsProjectionMap);
break;
case CONTROLS_ID:
qb.setTables(TABLE_NAME_CONTROLS);
qb.setProjectionMap(controlsProjectionMap);
selection = selection + "_id =?s " + uri.getLastPathSegment();
break;
case NUMBERS:
qb.setTables(TABLE_NAME_NUMBERS);
qb.setProjectionMap(numbersProjectionMap);
break;
case NUMBERS_ID:
qb.setTables(TABLE_NAME_NUMBERS);
qb.setProjectionMap(numbersProjectionMap);
selection = selection + "_id =?s " + uri.getLastPathSegment();
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case EVENTS:
count = db.update(TABLE_NAME_EVENTS, values, where, whereArgs);
break;
case CONTROLS:
count = db.update(TABLE_NAME_CONTROLS, values, where, whereArgs);
break;
case NUMBERS:
count = db.update(TABLE_NAME_NUMBERS, values, where, whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
РЕДАКТИРОВАТЬ: FragControl:
public class FragControls extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int CONTROLS_LOADER = 0x01;
SimpleCursorAdapter mAdapter;
ContentResolver resolver;
String mCurFilter;
DbOp db;
private String numberSelected = "0";
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
resolver= getActivity().getContentResolver();
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText(this.getString(R.string.add_control));
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { MyContentProvider.Data.C_TITLE, MyContentProvider.Data.C_LAST },
new int[] { android.R.id.text1, android.R.id.text2 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getActivity().getSupportLoaderManager().initLoader(CONTROLS_LOADER, null, this);
db= new DbOp();
getActivity().registerForContextMenu(getListView());
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_controls, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_add_control:
Intent addContrInt = new Intent(getActivity(), ActNewControl.class);
addContrInt.putExtra("contrNumber", numberSelected);
startActivity(addContrInt);
break;
}
return super.onOptionsItemSelected(item);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
String selection= Data.C_ID+" = ?";
String[] args={String.valueOf(id)};
Cursor c=resolver.query(Data.CONTENT_URI_CONTROLS, null, selection, args, null);
c.moveToFirst();
String text = c.getString(c.getColumnIndex(Data.C_TEXT));
String number = c.getString(c.getColumnIndex(Data.C_NUMBER));
c.close();
sendSMS(number, text);
Log.i("FragmentComplexList", "Item clicked: " + id);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
android.view.MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.contr_context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
} catch (ClassCastException e) {
Log.e("", "bad menuInfo", e);
return false;
}
long id = getListAdapter().getItemId(info.position);
switch (item.getItemId()){
case R.id.cm_delete:
String selection= MyContentProvider.Data.C_ID +"='"+ id+"'";
resolver.delete( MyContentProvider.Data.CONTENT_URI_CONTROLS,
selection, null);
break;
case R.id.cm_edit:
Intent editContrInt= new Intent(getActivity(), ActNewControl.class);
editContrInt.putExtra("contrNumber", numberSelected);
editContrInt.putExtra("contrId", id);
startActivity(editContrInt);
break;
}
Log.d("", "id = " + id);
Toast.makeText(getActivity(), "id = " + id, Toast.LENGTH_SHORT).show();
return true;
}
static final String[] SUMMARY_PROJECTION = new String[] {
MyContentProvider.Data.C_ID,
MyContentProvider.Data.C_TITLE,
MyContentProvider.Data.C_TEXT,
MyContentProvider.Data.C_LAST,
MyContentProvider.Data.C_NUMBER,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selection= MyContentProvider.Data.C_NUMBER +"=?";
String[] selectionArgs= {numberSelected};
return new CursorLoader(getActivity(), MyContentProvider.Data.CONTENT_URI_CONTROLS,
SUMMARY_PROJECTION, selection, selectionArgs,
null);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
public void setNumberSelected(String number){
numberSelected = number;
getActivity().getSupportLoaderManager().restartLoader(CONTROLS_LOADER, null, this);
}}
FragEvents:
public class FragEvents extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>{
@Override
public void onPause() {
db.allRead(resolver);
super.onPause();
}
private static final int EVENTS_LOADER = 0x02;
private String numberSelected="0";
ContentResolver resolver;
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
// If non-null, this is the current filter the user has provided.
String mCurFilter;
DbOp db;
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText(this.getString(R.string.perform_event));
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new EventsAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { MyContentProvider.Data.E_TEXT, MyContentProvider.Data.E_DATE,
MyContentProvider.Data.E_NUMBER, MyContentProvider.Data.E_TYPE },
new int[] { android.R.id.text1, android.R.id.text2 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getActivity().getSupportLoaderManager().initLoader(EVENTS_LOADER, null, this);
resolver = getActivity().getContentResolver();
db= new DbOp();
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_events, menu);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
//TODO Insert desired behavior here.
Log.i("FragmentComplexList", "Item clicked: " + id);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
android.view.MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.events_context_menu, menu);
}
@SuppressWarnings("deprecation")
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
} catch (ClassCastException e) {
Log.e("", "bad menuInfo", e);
return false;
}
long id = getListAdapter().getItemId(info.position);
switch (item.getItemId()){
case R.id.cm_delete:
String selection= MyContentProvider.Data.E_ID +"='"+ id+"'";
resolver.delete( MyContentProvider.Data.CONTENT_URI_EVENTS,
selection, null);
break;
case R.id.cm_copy_text:
//TODO copiare testo negli appunti
Cursor curs= mAdapter.getCursor();
curs.moveToPosition(info.position);
String text1 = curs.getString(curs.getColumnIndex(MyContentProvider.Data.E_TEXT));
curs.close();
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text1);
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("event text",text1);
clipboard.setPrimaryClip(clip);
}
break;
case R.id.cm_share:
//TODO condividere testo
Cursor cur= mAdapter.getCursor();
cur.moveToPosition(info.position);
String text = cur.getString(cur.getColumnIndex(MyContentProvider.Data.E_TEXT));
cur.close();
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(sharingIntent, "Share using"));
break;
}
Log.d("", "id = " + id);
Toast.makeText(getActivity(), "id = " + id, Toast.LENGTH_SHORT).show();
return true;
}
// These are the Contacts rows that we will retrieve.
static final String[] SUMMARY_PROJECTION = new String[] {
MyContentProvider.Data.E_ID,
MyContentProvider.Data.E_DATE,
MyContentProvider.Data.E_NUMBER,
MyContentProvider.Data.E_TEXT,
MyContentProvider.Data.E_TYPE,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selection= MyContentProvider.Data.E_NUMBER +" = ?";
String[] selectionArgs= {numberSelected};
return new CursorLoader(getActivity(), MyContentProvider.Data.CONTENT_URI_EVENTS,
SUMMARY_PROJECTION, selection, selectionArgs,
Data.E_ID + " DESC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
public void setNumberSelected(String number){
numberSelected = number;
getActivity().getSupportLoaderManager().restartLoader(EVENTS_LOADER, null, this);
}
}
Примечание:
Эти 2 фрагмента не добавят пункт меню, я думаю, что это ошибка ActionBarSherlock, но если я расширю SherlokListFragment, я получу ошибку, потому что onOptionsItemSelected() является окончательным, и я не могу переопределить его.
1 ответ
1 Вы можете лучше объяснить, в чем проблема, я не понял.
+2 Я думаю, что вместо:
String selection = MyContentProvider.Data.C_ID + "=";
String[] args = {+ String.valueOf(id)}; // what is with the + sign??
Вы хотите это:
String selection = MyContentProvider.Data.C_ID + "= ?"; // the ? is the placeholder
String[] args = {String.valueOf(id)};
3 Попробуйте удалить приложение, затем переустановить его и запустить снова. Также для NUMBERS
таблица у вас есть эта строка в ContentProvider
Вставьте метод:
rowId = db.insert(TABLE_NAME_EVENTS, Data.N_TITLE, values);
Вы уверены, что это не так:
rowId = db.insert(TABLE_NAME_NUMBERS, Data.N_TITLE, values);
?