问题描述:

I wanted to play with a ContentProvider example but I ran into an issue I can't seem to solve.

This example consists of an Activity:

import android.content.ContentUris;

import android.content.ContentValues;

import android.database.Cursor;

import android.net.Uri;

import android.support.v4.widget.SimpleCursorAdapter;

import android.support.v7.app.ActionBarActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.ListView;

public class MainActivity extends ActionBarActivity

{

final String LOG_TAG = "myLogs";

final Uri CONTACT_URI = Uri.parse("content://zulfigarov.com.trainingprj.MyContactsProvider/contacts");

final String CONTACT_NAME = "name";

final String CONTACT_EMAIL = "email";

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Cursor cursor = getContentResolver().query(CONTACT_URI, null, null, null, null);

startManagingCursor(cursor);

String[] from = {"name", "email"};

int[] to = {android.R.id.text1, android.R.id.text2};

SimpleCursorAdapter adapter

= new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cursor, from, to, 0);

ListView lvContact = (ListView)findViewById(R.id.lvContacts);

lvContact.setAdapter(adapter);

}

public void onClickInsert(View view)

{

ContentValues cv = new ContentValues();

cv.put(CONTACT_NAME, "name 4");

cv.put(CONTACT_EMAIL, "email 4");

Uri newUri = getContentResolver().insert(CONTACT_URI, cv);

Log.d(LOG_TAG, "insert, result Uri: " + newUri.toString());

}

public void onClickUpdate(View view)

{

ContentValues cv = new ContentValues();

cv.put(CONTACT_NAME, "name 5");

cv.put(CONTACT_EMAIL, "email 5");

Uri uri = ContentUris.withAppendedId(CONTACT_URI, 2);

int cnt = getContentResolver().update(uri, cv, null, null);

Log.d(LOG_TAG, "update, count = " + cnt);

}

public void onClickDelete(View view)

{

Uri uri = ContentUris.withAppendedId(CONTACT_URI, 3);

int cnt = getContentResolver().delete(uri, null, null);

Log.d(LOG_TAG, "delete, count = " + cnt);

}

public void onClickError(View view)

{

Uri uri = Uri.parse("content://zulfigarov.com.trainingprj.MyContentProvider/phones");

try

{

Cursor cursor = getContentResolver().query(uri, null, null, null, null);

}

catch (Exception ex)

{

Log.d(LOG_TAG, "Error: " + ex.getClass() + ", " + ex.getMessage());

}

}

}

and a ContentProvider:

import android.content.ContentProvider;

import android.content.ContentUris;

import android.content.ContentValues;

import android.content.Context;

import android.content.UriMatcher;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

import android.net.Uri;

import android.text.TextUtils;

import android.util.Log;

public class MyContactsProvider extends ContentProvider

{

final String LOG_TAG = "myLogs";

static final String DB_NAME = "mydb";

static final int DB_VERSION = 1;

static final String CONTACT_TABLE = "contacts";

static final String CONTACT_ID = "_id";

static final String CONTACT_NAME = "name";

static final String CONTACT_EMAIL = "email";

static final String DB_CREATE = "CREATE TABLE " + CONTACT_TABLE + "("

+ CONTACT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "

+ CONTACT_NAME + " TEXT, "

+ CONTACT_EMAIL + " TEXT" + ");";

static final String AUTHORITY = "zulfigarov.com.trainingprj.MyContactsProvider";

static final String CONTACT_PATH = "contacts";

public static final Uri CONTACT_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + CONTACT_PATH);

static final String CONTACT_CONTENT_TYPE = "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + CONTACT_PATH;

static final String CONTACT_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd." + AUTHORITY + "." + CONTACT_PATH;

static final int URI_CONTACTS = 1;

static final int URI_CONTACTS_ID = 2;

private static final UriMatcher uriMatcher;

static

{

uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(AUTHORITY, CONTACT_PATH, URI_CONTACTS);

uriMatcher.addURI(AUTHORITY, CONTACT_PATH + "/#", URI_CONTACTS_ID);

}

DBHelper dbHelper;

SQLiteDatabase db;

@Override

public boolean onCreate()

{

Log.d(LOG_TAG, "onCreate provider");

dbHelper = new DBHelper(getContext());

return true;

}

@Override

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

{

Log.d(LOG_TAG,"query, " + uri.toString());

switch (uriMatcher.match(uri))

{

case URI_CONTACTS:

Log.d(LOG_TAG, "URI_CONTACTS");

if(TextUtils.isEmpty(sortOrder))

{

sortOrder = CONTACT_NAME + " ASC";

}

break;

case URI_CONTACTS_ID:

String id = uri.getLastPathSegment();

Log.d(LOG_TAG, "URI_CONTACTS_ID");

if (TextUtils.isEmpty(selection))

selection = CONTACT_ID + " = " + id;

else

selection = selection + " AND " + CONTACT_ID + " = " + id;

break;

default:

throw new IllegalArgumentException("Wrong URI: " + uri);

}

db = dbHelper.getWritableDatabase();

Cursor cursor = db.query(CONTACT_TABLE, projection, selection,

selectionArgs, null, null, sortOrder);

cursor.setNotificationUri(getContext().getContentResolver(),CONTACT_CONTENT_URI);

return cursor;

}

@Override

public String getType(Uri uri)

{

Log.d(LOG_TAG, "getTYpe, " + uri.toString());

switch (uriMatcher.match(uri))

{

case URI_CONTACTS:

return CONTACT_CONTENT_TYPE;

case URI_CONTACTS_ID:

return CONTACT_CONTENT_ITEM_TYPE;

}

return null;

}

@Override

public Uri insert(Uri uri, ContentValues values)

{

Log.d(LOG_TAG,"insert, " + uri.toString());

if(uriMatcher.match(uri) != URI_CONTACTS)

throw new IllegalArgumentException("Wrong URI: " + uri);

db = dbHelper.getWritableDatabase();

long rowID = db.insert(CONTACT_TABLE, null, values);

Uri resultUri = ContentUris.withAppendedId(CONTACT_CONTENT_URI, rowID);

getContext().getContentResolver().notifyChange(resultUri, null);

return resultUri;

}

@Override

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

{

Log.d(LOG_TAG,"delete, " + uri.toString());

switch (uriMatcher.match(uri))

{

case URI_CONTACTS:

Log.d(LOG_TAG,"URI_CONTACTS");

break;

case URI_CONTACTS_ID:

String id = uri.getLastPathSegment();

Log.d(LOG_TAG,"URI_CONTACTS_ID, " + id);

if(TextUtils.isEmpty(selection))

{

selection = CONTACT_ID + " = " + id;

}

else

{

selection = selection + " AND " + CONTACT_ID + " = " + id;

}

break;

default:

throw new IllegalArgumentException("Wrong URI: " + uri);

}

db = dbHelper.getWritableDatabase();

int cnt = db.delete(CONTACT_TABLE, selection, selectionArgs);

getContext().getContentResolver().notifyChange(uri, null);

return cnt;

}

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

{

Log.d(LOG_TAG,"update, " + uri.toString());

switch (uriMatcher.match(uri))

{

case URI_CONTACTS:

Log.d(LOG_TAG,"URI_CONTACTS");

break;

case URI_CONTACTS_ID:

String id = uri.getLastPathSegment();

Log.d(LOG_TAG, "URI_CONTACTS_ID");

if(TextUtils.isEmpty(selection))

{

selection = CONTACT_ID;

}

else

{

selection = selection + " AND " + CONTACT_ID + " = " + id;

}

break;

default:

throw new IllegalArgumentException("Wrong URI: " + uri);

}

db = dbHelper.getWritableDatabase();

int cnt = db.update(CONTACT_TABLE, values, selection, selectionArgs);

getContext().getContentResolver().notifyChange(uri,null);

return cnt;

}

private class DBHelper extends SQLiteOpenHelper

{

public DBHelper(Context context)

{

super(context, DB_NAME, null, DB_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db)

{

db.execSQL(DB_CREATE);

ContentValues cv = new ContentValues();

for (int i = 1; i <= 3; i++)

{

cv.put(CONTACT_NAME, "name " + i);

cv.put(CONTACT_EMAIL, "email " + i);

db.insert(CONTACT_TABLE, null, cv);

}

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

{

}

}

}

The touble is that when I click on the buttons (firing onClickInsert, onClickUpdate etc. methods in MainActivity) it updates the data in database but doesn't update the ListView on an activity. Looks like

getContext().getContentResolver().notifyChange(resultUri, null);

is not working properly. So I can't find where i'm wrong.

网友答案:

Use CursorLoaders to load the data and populate the ListView.

http://developer.android.com/reference/android/content/CursorLoader.html

Then use getContext().getContentResolver().notifyChange(resultUri, null); when you insert, update or delete!

Without CursorLoaders you will have to use ContentObservers

So, although DB is updated in background and you are using notifyChange() but no one is listening to that!

网友答案:

You should be calling adapter.notifyDataSetChanged() (after the onClickInsert) in order to make your ListView notice about the change.

相关阅读:
Top