startManagingCursor를 사용하는 대신 콘텐츠 공급자와 CursorLoader를 사용하도록 응용 프로그램을 업데이트하고 있습니다.콘텐츠 공급자 urimatching CASE 문을 두 번 호출하는 중
내 sqlite 데이터베이스에 2 개의 테이블이 있으며 테이블 오류와 테이블 메시지가 있습니다. 이 테이블의 내용을 listview에 표시하는 활동을 시작하면 모든 것이 잘 작동하는 것 같습니다.
내가 주목 한 사실 중 하나는 viewMessages 활동을 호출 할 때 콘텐츠 공급자의 URI와 일치하는 Case 문이 두 번 호출된다는 것입니다.
이것은 viewPhoneNumbers 활동을 호출 할 때 발생하지 않습니다. 난 당신이 무슨 뜻인지 볼 수 있도록 두 번
cursorLoader = new CursorLoader(this, RR3ContentProvider.CONTENT_URI_MESSAGES, projection, null, null, null);
내가 먼저 로깅 문을 보여주지 다음 호출하고 같은
보인다. 그것은 'CASE Messages'를 두 번 기록하지만, 전화 테이블에 대해 동일한 작업을 수행하면 'Case PHONES'가 한 번만 기록됩니다. 단 한번만 기록하면됩니다.
사례 메시지가 두 번 실행되는 이유는 누구에게 말해 줄 수 있습니까?
07-22 10:17:11.845: E/ViewMessagesActivityAsync(10808): inside ViewMessagesActivityAsync oncreate
07-22 10:17:11.845: E/RR3ContentProvider(10808): inside RR3ContentProvider query method
07-22 10:17:11.845: E/RR3ContentProvider(10808): CASE MESSAGES
07-22 10:17:11.845: E/RR3ContentProvider(10808): About to do the query method in content provider
07-22 10:17:11.855: E/ViewMessagesActivityAsync(10808): inside3 onCreateLoader in ViewMessagesActivityAsync
07-22 10:17:11.855: E/RR3ContentProvider(10808): inside RR3ContentProvider query method
07-22 10:17:11.855: E/RR3ContentProvider(10808): CASE MESSAGES
07-22 10:17:11.855: E/RR3ContentProvider(10808): About to do the query method in content provider
07-22 10:17:11.915: V/PhoneStatusBar(1219): setLightsOn(true)
07-22 10:17:11.945: E/ViewMessagesActivityAsync(10808): inside myadapter getview for messages
07-22 10:17:11.945: E/ViewMessagesActivityAsync(10808): (Cursor)getItem(position) = [email protected]ion = 0
07-22 10:17:11.945: E/ViewMessagesActivityAsync(10808): inside myadapter getview for messages
07-22 10:17:11.945: E/ViewMessagesActivityAsync(10808): (Cursor)getItem(position) = [email protected]ion = 1
07-22 10:17:11.955: E/ViewMessagesActivityAsync(10808): inside myadapter getview for messages
07-22 10:17:11.955: E/ViewMessagesActivityAsync(10808): (Cursor)getItem(position) = [email protected]ion = 2
.
07-22 10:17:21.345: E/ViewPhoneNumberAsync(10808): inside ViewPhoneNumberAsync onCreate
07-22 10:17:21.345: E/RR3ContentProvider(10808): inside RR3ContentProvider query method
07-22 10:17:21.345: E/RR3ContentProvider(10808): CASE PHONES
07-22 10:17:21.345: E/RR3ContentProvider(10808): About to do the query method in content provider
07-22 10:17:21.405: V/PhoneStatusBar(1219): setLightsOn(true)
07-22 10:17:21.425: E/ViewPhoneNumberAsync(10808): inside myadapter getview
07-22 10:17:21.435: E/ViewPhoneNumberAsync(10808): inside myadapter getview
. ViewPhoneNumberAsync
public class ViewPhoneNumberAsync extends Activity implements LoaderCallbacks<Cursor> {
ListView listView;
MyAdapter mAdapter;
LoaderManager loadermanager;
CursorLoader cursorLoader;
private static final String TAG = ViewPhoneNumberAsync.class.getSimpleName();
final String BACKPRESS_ACTION = "com.carefreegroup.rr3.BACKPRESS_ACTION";
private final String TABLEPHONE = "phone";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "inside ViewPhoneNumberAsync onCreate");
loadermanager=getLoaderManager();
// setup UI
setContentView(R.layout.viewphonenumbers);
//transactionCount = (TextView)findViewById(R.id.textviewtransactionsfordaycount);
listView = (ListView) findViewById(R.id.listviewphonenumbers);
String[] from = { LoginValidate.C_PHONE_NAME, LoginValidate.C_PHONE_NUMBER};
int[] to = { R.id.phonename, R.id.phonenumber };
// String[] uiBindFrom = { TABLEPHONE};
// int[] uiBindTo = {android.R.id.text1};
/*Empty adapter that is used to display the loaded data*/
mAdapter = new MyAdapter(this, R.layout.rowphonenumbers, null, from, to,0);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(mAdapter);
loadermanager.initLoader(1, null, this);
}
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
String[] projection = { LoginValidate.C_ID_PHONE, LoginValidate.C_PHONE_NAME, LoginValidate.C_PHONE_NUMBER };
cursorLoader = new CursorLoader(this, RR3ContentProvider.CONTENT_URI_PHONE_NUMBERS, projection, null, null, null);
return cursorLoader;
}
public void onLoadFinished(Loader<Cursor> loader,Cursor cursor) {
if(mAdapter!=null && cursor!=null)
mAdapter.swapCursor(cursor); //swap the new cursor in.
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
public void onLoaderReset(Loader<Cursor> arg0) {
if(mAdapter!=null)
mAdapter.swapCursor(null);
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
@Override
public void onBackPressed() {
super.onBackPressed();
Intent i = new Intent(this, NfcscannerActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//i.setAction(QRCODE_ACTION);
i.setAction(BACKPRESS_ACTION);
startActivity(i);
}
private class MyAdapter extends SimpleCursorAdapter implements OnItemClickListener {
public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
}
.
ViewMessagesAsync
public class ViewMessagesActivityAsync extends Activity implements LoaderCallbacks<Cursor>{
private static final String TAG = ViewMessagesActivityAsync.class.getSimpleName();
final String BACKPRESS_ACTION = "com.carefreegroup.rr3.BACKPRESS_ACTION";
NfcScannerApplication nfcscannerapplication;
Cursor cursorMessages;
ListView listView;
SimpleCursorAdapter adapter;
MyAdapter myAdapter;
TextView noMessages;
ArrayList<String> guidArray;
LoaderManager loadermanager;
CursorLoader cursorLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "inside ViewMessagesActivityAsync oncreate");
setContentView(R.layout.viewmessages);
nfcscannerapplication = (NfcScannerApplication) getApplication();
loadermanager=getLoaderManager();
guidArray = new ArrayList<String>();
listView = (ListView) findViewById(R.id.listviewmessages);
noMessages = (TextView)findViewById(R.id.textviewnomessageslabel);
cursorMessages = getContentResolver().query(RR3ContentProvider.CONTENT_URI_MESSAGES, null, null, null, null);
if(cursorMessages.getCount() == 0){
noMessages.setVisibility(View.VISIBLE);
listView.setVisibility(View.GONE);
}else{
listView.setVisibility(View.VISIBLE);
noMessages.setVisibility(View.GONE);
}
String[] from = { LoginValidate.C_MESSAGE_CREATED_AT, LoginValidate.C_MESSAGE_TEXT, LoginValidate.C_MESSAGE_SENDER};
int[] to = { R.id.messagecreatedat, R.id.messagetext, R.id.messagesender};
myAdapter = new MyAdapter(nfcscannerapplication, R.layout.rowmessages, null, from, to, 0);
listView.setAdapter(myAdapter);
listView.setOnItemClickListener(myAdapter);
loadermanager.initLoader(1, null, this);
}//end of onCreate
@Override
protected void onResume() {
super.onResume();
}
private class MyAdapter extends SimpleCursorAdapter implements OnItemClickListener {
Cursor c;
String messageGuid;
public MyAdapter(Context context, int layout, Cursor c, String[] from,
int[] to, int flags) {
super(context, layout, c, from, to, flags);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.e(TAG, "inside3 onCreateLoader in ViewMessagesActivityAsync");
String[] projection = { LoginValidate.C_ID_MESSAGE,LoginValidate.C_MESSAGE_GUID,LoginValidate.C_MESSAGE_CREATED_AT, LoginValidate.C_MESSAGE_TEXT,
LoginValidate.C_MESSAGE_SENDER , LoginValidate.C_MESSAGE_REPLIED, LoginValidate.C_MESSAGE_SEEN, LoginValidate.C_MESSAGE_DISPLAYED,
LoginValidate.C_MESSAGE_REPLY_MESSAGE, LoginValidate.C_MESSAGE_IS_STANDALONE};
cursorLoader = new CursorLoader(this, RR3ContentProvider.CONTENT_URI_MESSAGES, projection, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if(myAdapter!=null && cursor!=null)
myAdapter.swapCursor(cursor); //swap the new cursor in.
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
if(myAdapter!=null)
myAdapter.swapCursor(null);
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
}
컨텐트 프로
public class RR3ContentProvider extends ContentProvider {
private static final String TAG = RR3ContentProvider.class.getSimpleName();
NfcScannerApplication nfcAppObj;
static final String PROVIDER_NAME = "com.carefreegroup.rr3.ContentProvider";
static final String URLPHONENUMBERS = "content://" + PROVIDER_NAME + "/phonenumbers";
static final Uri CONTENT_URI_PHONE_NUMBERS = Uri.parse(URLPHONENUMBERS);
static final String _ID_PHONENUMBERS = "_id";
static final String PHONE_NAME = "phonename";
static final String PHONE_NUMBER = "phonenumber";
static final String TABLEPHONE = "phone";
private static HashMap<String, String> PHONE_PROJECTION_MAP;
static final int PHONES = 1;
static final int PHONE_ID = 2;
static final String URLMESSAGES = "content://" + PROVIDER_NAME + "/messages";
static final Uri CONTENT_URI_MESSAGES = Uri.parse(URLMESSAGES);
static final String _ID_MESSAGES = "_id";
static final String MESSAGE_CREATED_AT = "messagecreatedat";
static final String MESSAGE_TEXT = "messagetext";
static final String MESSAGE_SENDER = "messagesender";
static final String TABLEMESSAGE = "message";
private static HashMap<String, String> MESSAGE_PROJECTION_MAP;
static final int MESSAGES = 3;
static final int MESSAGE_ID = 4;
static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "phonenumbers", PHONES);
uriMatcher.addURI(PROVIDER_NAME, "phonenumbers/#", PHONE_ID);
uriMatcher.addURI(PROVIDER_NAME, "messages", MESSAGES);
uriMatcher.addURI(PROVIDER_NAME, "messages/#", MESSAGE_ID);
}
/**
* Database specific constant declarations
*/
private SQLiteDatabase db;
@Override
public boolean onCreate() {
Context context = getContext();
nfcAppObj = (NfcScannerApplication) getContext();
Log.e(TAG, "inside RR3ContentProvider onCreate");
return (nfcAppObj == null)? false:true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
db = nfcAppObj.getDb();
/**
* Add a new student record
*/
long rowID = db.insert( TABLEPHONE, "", values);
/**
* If record is added successfully
*/
if (rowID > 0)
{
Uri _uri = ContentUris.withAppendedId(CONTENT_URI_PHONE_NUMBERS, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to add a record into " + uri);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.e(TAG, "inside RR3ContentProvider query method");
db = nfcAppObj.getDb();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri)) {
case PHONES:
Log.e(TAG, "CASE PHONES");
qb.setTables(TABLEPHONE);
qb.setProjectionMap(PHONE_PROJECTION_MAP);
break;
case PHONE_ID:
Log.e(TAG, "CASE PHONE_ID");
qb.setTables(TABLEPHONE);
qb.appendWhere(_ID_PHONENUMBERS + "=" + uri.getPathSegments().get(1));
break;
case MESSAGES:
Log.e(TAG, "CASE MESSAGES");
qb.setTables(TABLEMESSAGE);
qb.setProjectionMap(MESSAGE_PROJECTION_MAP);
break;
case MESSAGE_ID:
Log.e(TAG, "CASE MESAAGE_ID");
qb.setTables(TABLEMESSAGE);
qb.appendWhere(_ID_MESSAGES + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
switch (uriMatcher.match(uri)) {
case PHONES:
if (sortOrder == null || sortOrder == ""){
sortOrder = PHONE_NAME;
}
break;
case PHONE_ID:
if (sortOrder == null || sortOrder == ""){
sortOrder = PHONE_NAME;
}
break;
case MESSAGES:
if (sortOrder == null || sortOrder == ""){
sortOrder = MESSAGE_CREATED_AT + " DESC";
}
break;
case MESSAGE_ID:
if (sortOrder == null || sortOrder == ""){
sortOrder = MESSAGE_CREATED_AT + " DESC";
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
Log.e(TAG, "About to do the query method in content provider");
Cursor c = qb.query(db, projection, selection, selectionArgs,
null, null, sortOrder);
/**
* register to watch a content URI for changes
*/
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}//end of query
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
db = nfcAppObj.getDb();
int count = 0;
switch (uriMatcher.match(uri)){
case PHONES:
count = db.delete(TABLEPHONE, selection, selectionArgs);
break;
case PHONE_ID:
String id = uri.getPathSegments().get(1);
count = db.delete(TABLEPHONE, _ID_PHONENUMBERS + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
case MESSAGES:
count = db.delete(TABLEMESSAGE, selection, selectionArgs);
break;
case MESSAGE_ID:
String id2 = uri.getPathSegments().get(1);
count = db.delete(TABLEMESSAGE, _ID_MESSAGES + " = " + id2 +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
db = nfcAppObj.getDb();
int count = 0;
switch (uriMatcher.match(uri)){
case PHONES:
count = db.update(TABLEPHONE, values,
selection, selectionArgs);
break;
case PHONE_ID:
count = db.update(TABLEPHONE, values, _ID_PHONENUMBERS +
" = " + uri.getPathSegments().get(1) +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
case MESSAGES:
count = db.update(TABLEMESSAGE, values,
selection, selectionArgs);
break;
case MESSAGE_ID:
count = db.update(TABLEMESSAGE, values, _ID_MESSAGES +
" = " + uri.getPathSegments().get(1) +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}//end of delete
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)){
/**
* Get all records
*/
case PHONES:
return "vnd.android.cursor.dir/vnd.example.phonenumbers";
/**
* Get a particular record
*/
case PHONE_ID:
return "vnd.android.cursor.item/vnd.example.phonenumbers";
/**
* Get all records
*/
case MESSAGES:
return "vnd.android.cursor.dir/vnd.example.messages";
/**
* Get a particular record
*/
case MESSAGE_ID:
return "vnd.android.cursor.item/vnd.example.messages";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}