컨텍스트 :
Android에서는 모든 연락처 DataSet<ContactEntry>
에 대한 단일 소스를 구현하려고합니다. 따라서 연락처가 동기화 프로세스에 의해 업데이트되면 기존 어댑터에 반영되어야합니다 (활성 어댑터가있는 경우에만).
그러나 동기화에서 항상 DataSet<ContactEntry>
(null이 아니더라도)을 찾음으로써 동기화의 모든 업데이트/추가/제거가 무시됩니다.왜 단일 정적 변수가 다중 읽기에 대해 다중 값을 갖는가?
소스 코드 :
public class ContactsDataSet {
private static final String TAG = "ContactsDataSet";
private static final Object lock = new Object();
private static volatile WeakReference<DataSet<ContactEntry>> instance = null;
public static DataSet<ContactEntry> getInstance(Context context) {
synchronized (lock) {
DataSet<ContactEntry> dataSet;
if (instance == null) {
Log.d(TAG, "Creating instance for ContactsDataSet");
dataSet = createDataSet(context);
instance = new WeakReference<>(dataSet);
Log.d(TAG, "Set instance to: " + instance + " on " + Thread.currentThread().getName());
} else {
dataSet = instance.get();
if (dataSet == null) {
Log.d(TAG, "Re-creating Data Set");
dataSet = createDataSet(context);
instance = new WeakReference<>(dataSet);
Log.d(TAG, "Set instance to: " + instance + " on " + Thread.currentThread().getName());
} else {
Log.d(TAG, "Valid instance: " + instance + " on " + Thread.currentThread().getName());
}
}
return dataSet;
}
}
public static void printInstance() {
synchronized (lock) {
Log.d(TAG, "printInstance() => " + instance + " on " + Thread.currentThread().getName());
}
}
private static DataSet<ContactEntry> getInstance() {
synchronized (lock) {
DataSet<ContactEntry> ret= instance == null ? null : instance.get();
Log.d(TAG, "getInstance() => " + instance + " on " + Thread.currentThread().getName());
return ret;
}
}
private static DataSet<ContactEntry> createDataSet(Context context) {
Log.d(TAG, "Fetching contacts from DB");
return new DataSet<>(DbHelper.getInstance(context).fetchValidContacts());
}
public static void addContact(ContactEntry contact) {
if (contact.isDirty() || TextUtils.isEmpty(contact.getUserNumber())) {
Log.d(TAG, "Ignoring dirty/incomplete contact");
return;
}
synchronized (lock) {
DataSet<ContactEntry> dataSet = getInstance();
if (dataSet != null) {
Log.d(TAG, "Adding " + contact + " to Cache");
dataSet.addItem(contact);
} else {
Log.d(TAG, "Ignoring new Contact " + contact + " as instance: " + instance + " isn't valid on " + Thread.currentThread().getName());
}
}
}
public static void updateContact(ContactEntry contact) {
if (contact.isDirty() || TextUtils.isEmpty(contact.getUserNumber())) {
Log.d(TAG, "Removing dirty/incomplete contact");
deleteContact(contact.getContactId());
}
synchronized (lock) {
DataSet<ContactEntry> dataSet = getInstance();
if (dataSet != null) {
Log.d(TAG, "Updating " + contact + " in Cache");
dataSet.updateItem(contact);
} else {
Log.d(TAG, "Ignoring update Contact " + contact + " as instance: " + instance + " isn't valid on " + Thread.currentThread().getName());
}
}
}
public static void deleteContact(int contactId) {
synchronized (lock) {
DataSet<ContactEntry> dataSet = getInstance();
if (dataSet != null) {
Log.d(TAG, "Removing " + contactId + " from Cache");
dataSet.removeItem(contactId);
} else {
Log.d(TAG, "Ignoring delete Contact " + contactId + " as instance: " + instance + " isn't valid on " + Thread.currentThread().getName());
}
}
}
}
DataSet
클래스는 관찰자의 목록과 간단한 목록입니다.
getInstance(Context context)
이 호출 될 때 instance
은 항상 (처음에는 아니고) 값을가집니다. getInstance()
이 방법 addContact
, updateContact
deleteContact
또는 임의로부터 호출
그러나, 정적 변수 instance
항상 null
값을 갖는다 (나사 이름이 같은 경우에도 주된).
instance
변수 volatile
으로 Multidex 지원을 제거했지만 작동하지 못했습니다. 어떤 도움이든지 큰 도움이 될 것입니다. 미리 감사드립니다!
로그 :
When I first invoke Adapter:
09-03 18:01:04.367 18369-18369/in.yyyyyyy.xxxxx D/ContactsAdapter: ContactsAdapter()
09-03 18:01:04.369 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: Creating instance for ContactsDataSet
09-03 18:01:04.369 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: Fetching contacts from DB
09-03 18:01:04.398 18369-18369/in.yyyyyyy.xxxxx I/ContactEntry: fetchValidContacts() => [ContactEntry { contactId: 1, contactVersion: 4, phoneNumber: +999999999999, email: null, userNumber: 7dc5baec-1e08-43f4-b124-8d65d097036e, name: CCCCCCCCCCCCCC, dirty: false }, ContactEntry { contactId: 3, contactVersion: 3, phoneNumber: +333333333333, email: null, userNumber: 13d7b667-b523-41b7-ba89-203139e0dba9, name: GGGGGG, dirty: false }, ContactEntry { contactId: 4, contactVersion: 20, phoneNumber: +999999999999, email: null, userNumber: 7dc5baec-1e08-43f4-b124-8d65d097036e, name: MMMMMM, dirty: false }]
09-03 18:01:04.398 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: Set instance to: [email protected] on main
09-03 18:01:04.398 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: printInstance() => [email protected] on main
Triggered Sync (after updating 3rd contact - MMMMMM):
09-03 18:02:43.986 28748-28748/in.yyyyyyy.xxxxx:sync D/SyncContacts: Updating User Number for ContactEntry { contactId: 4, contactVersion: 21, phoneNumber: +333333333333, email: null, userNumber: null, name: MMMMMM, dirty: true } with 13d7b667-b523-41b7-ba89-203139e0dba9
09-03 18:02:43.986 28748-28748/in.yyyyyyy.xxxxx:sync I/ContactEntry: updateAccount(ContactEntry { contactId: 4, contactVersion: 21, phoneNumber: +333333333333, email: null, userNumber: 13d7b667-b523-41b7-ba89-203139e0dba9, name: MMMMMM, dirty: false })
09-03 18:02:43.992 28748-28748/in.yyyyyyy.xxxxx:sync D/ContactsDataSet: getInstance() => null on main
09-03 18:02:43.992 28748-28748/in.yyyyyyy.xxxxx:sync D/ContactsDataSet: Ignoring update Contact ContactEntry { contactId: 4, contactVersion: 21, phoneNumber: +333333333333, email: null, userNumber: 13d7b667-b523-41b7-ba89-203139e0dba9, name: MMMMMM, dirty: false } as instance: null isn't valid on main
When I invoke Adapter again:
09-03 18:07:40.255 18369-18369/in.yyyyyyy.xxxxx D/ContactsAdapter: ContactsAdapter()
09-03 18:07:40.257 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: Valid instance: [email protected] on main
09-03 18:07:40.257 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: printInstance() => [email protected] on main
인스턴스가 null이거나 instance.get()이 null입니까? –
인스턴스가 null입니다. – Siva
MCVE 규칙 적용에 대한 변경 사항이 있습니까? http://stackoverflow.com/help/mcve –