上下文
在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
class是一个包含Observers列表的简单列表。
调用getInstance(Context context)
时,instance
始终有值(当然,不是第一次)。
但是,当从任何方法getInstance()
,addContact
或updateContact
调用deleteContact
时,静态变量instance
始终具有值null
(偶数)当线程名称相同时:main)。
我尝试删除Multidex支持,使instance
变量volatile
但无法使其正常工作。任何帮助都会得到很好的帮助。提前谢谢!
日志:
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: java.lang.ref.WeakReference@90e9b43 on main
09-03 18:01:04.398 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: printInstance() => java.lang.ref.WeakReference@90e9b43 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: java.lang.ref.WeakReference@90e9b43 on main
09-03 18:07:40.257 18369-18369/in.yyyyyyy.xxxxx D/ContactsDataSet: printInstance() => java.lang.ref.WeakReference@90e9b43 on main
答案 0 :(得分:2)
问题在于Sync Service作为不同的进程启动。我知道单个Android进程可以拥有多个Linux进程。同步服务配置:
<service
android:name=".sync.SyncService" android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
我从互联网上的其他应用程序复制了该配置,却不知道android:process
是什么。
我删除了属性android:process
,它开始工作。