mirror of https://github.com/M66B/FairEmail.git
Fixed multiple observers
This commit is contained in:
parent
3aa89cae97
commit
c4733427ae
|
@ -96,6 +96,7 @@ import androidx.core.content.ContextCompat;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.paging.AsyncPagedListDiffer;
|
||||
|
@ -188,6 +189,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
private Group grpAttachments;
|
||||
private Group grpExpanded;
|
||||
|
||||
private LiveData<List<EntityAttachment>> liveAttachments = null;
|
||||
private Observer<List<EntityAttachment>> observerAttachments = null;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
|
@ -400,25 +404,16 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
}
|
||||
|
||||
if (debug) {
|
||||
db.operation().getOperationsByMessage(message.id).removeObservers(owner);
|
||||
db.operation().getOperationsByMessage(message.id).observe(owner, new Observer<List<EntityOperation>>() {
|
||||
@Override
|
||||
public void onChanged(List<EntityOperation> operations) {
|
||||
String text = message.error +
|
||||
"\n" + message.uid + "/" + message.id + " " + df.format(new Date(message.received)) +
|
||||
"\n" + (message.ui_hide ? "HIDDEN " : "") +
|
||||
"seen=" + message.seen + "/" + message.ui_seen + "/" + message.unseen +
|
||||
" found=" + message.ui_found +
|
||||
"\n" + message.msgid +
|
||||
"\n" + message.thread;
|
||||
if (operations != null)
|
||||
for (EntityOperation op : operations)
|
||||
text += "\n" + op.id + ":" + op.name + " " + df.format(new Date(op.created));
|
||||
String text = message.error +
|
||||
"\n" + message.uid + "/" + message.id + " " + df.format(new Date(message.received)) +
|
||||
"\n" + (message.ui_hide ? "HIDDEN " : "") +
|
||||
"seen=" + message.seen + "/" + message.ui_seen + "/" + message.unseen +
|
||||
" found=" + message.ui_found +
|
||||
"\n" + message.msgid +
|
||||
"\n" + message.thread;
|
||||
|
||||
tvError.setText(text);
|
||||
tvError.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
tvError.setText(text);
|
||||
tvError.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
tvError.setText(message.error);
|
||||
tvError.setVisibility(message.error == null ? View.GONE : View.VISIBLE);
|
||||
|
@ -451,9 +446,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
grpAttachments.setVisibility(message.attachments > 0 && show_expanded ? View.VISIBLE : View.GONE);
|
||||
grpExpanded.setVisibility(viewType == ViewType.THREAD && show_expanded ? View.VISIBLE : View.GONE);
|
||||
|
||||
db.folder().liveSystemFolders(message.account).removeObservers(owner);
|
||||
db.attachment().liveAttachments(message.id).removeObservers(owner);
|
||||
|
||||
bnvActions.setTag(null);
|
||||
|
||||
if (show_expanded) {
|
||||
|
@ -488,9 +480,18 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
bodyTask.load(context, owner, args);
|
||||
}
|
||||
|
||||
db.folder().liveSystemFolders(message.account).observe(owner, new Observer<List<EntityFolder>>() {
|
||||
Bundle sargs = new Bundle();
|
||||
sargs.putLong("account", message.account);
|
||||
|
||||
new SimpleTask<List<EntityFolder>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<EntityFolder> folders) {
|
||||
protected List<EntityFolder> onLoad(Context context, Bundle args) {
|
||||
long account = args.getLong("account");
|
||||
return DB.getInstance(context).folder().getSystemFolders(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, List<EntityFolder> folders) {
|
||||
boolean hasJunk = false;
|
||||
boolean hasTrash = false;
|
||||
boolean hasArchive = false;
|
||||
|
@ -524,30 +525,43 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
bnvActions.setVisibility(View.VISIBLE);
|
||||
vSeparatorBody.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Helper.unexpectedError(context, owner, ex);
|
||||
}
|
||||
}.load(context, owner, sargs);
|
||||
|
||||
// Observe attachments
|
||||
db.attachment().liveAttachments(message.id).observe(owner,
|
||||
new Observer<List<EntityAttachment>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<EntityAttachment> attachments) {
|
||||
if (attachments == null)
|
||||
attachments = new ArrayList<>();
|
||||
observerAttachments = new Observer<List<EntityAttachment>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<EntityAttachment> attachments) {
|
||||
if (attachments == null)
|
||||
attachments = new ArrayList<>();
|
||||
|
||||
adapter.set(attachments);
|
||||
adapter.set(attachments);
|
||||
|
||||
if (message.content) {
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("message", message);
|
||||
bodyTask.load(context, owner, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (message.content) {
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("message", message);
|
||||
bodyTask.load(context, owner, args);
|
||||
}
|
||||
}
|
||||
};
|
||||
liveAttachments = db.attachment().liveAttachments(message.id);
|
||||
liveAttachments.observe(owner, observerAttachments);
|
||||
}
|
||||
|
||||
itemView.setActivated(selectionTracker != null && selectionTracker.isSelected(message.id));
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
if (liveAttachments != null) {
|
||||
liveAttachments.removeObserver(observerAttachments);
|
||||
liveAttachments = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
int pos = getAdapterPosition();
|
||||
|
@ -1040,10 +1054,14 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
}
|
||||
|
||||
private void onAnswer(final ActionData data) {
|
||||
final DB db = DB.getInstance(context);
|
||||
db.answer().liveAnswers().observe(owner, new Observer<List<EntityAnswer>>() {
|
||||
new SimpleTask<List<EntityAnswer>>() {
|
||||
@Override
|
||||
public void onChanged(List<EntityAnswer> answers) {
|
||||
protected List<EntityAnswer> onLoad(Context context, Bundle args) {
|
||||
return DB.getInstance(context).answer().getAnswers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, List<EntityAnswer> answers) {
|
||||
if (answers == null || answers.size() == 0) {
|
||||
Snackbar snackbar = Snackbar.make(
|
||||
itemView,
|
||||
|
@ -1094,10 +1112,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
|
||||
popupMenu.show();
|
||||
}
|
||||
|
||||
db.answer().liveAnswers().removeObservers(owner);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Helper.unexpectedError(context, owner, ex);
|
||||
}
|
||||
}.load(context, owner, new Bundle());
|
||||
}
|
||||
|
||||
private void onUnseen(final ActionData data) {
|
||||
|
@ -1616,6 +1637,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
holder.unbind();
|
||||
holder.unwire();
|
||||
|
||||
TupleMessageEx message = differ.getItem(position);
|
||||
|
@ -1627,6 +1649,11 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull ViewHolder holder) {
|
||||
holder.unbind();
|
||||
}
|
||||
|
||||
void setSelectionTracker(SelectionTracker<Long> selectionTracker) {
|
||||
this.selectionTracker = selectionTracker;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,11 @@ public interface DaoFolder {
|
|||
@Query("SELECT * FROM folder ORDER BY account, name")
|
||||
List<EntityFolder> getFolders();
|
||||
|
||||
@Query("SELECT * FROM folder" +
|
||||
" WHERE folder.account = :account" +
|
||||
" AND type <> '" + EntityFolder.USER + "'")
|
||||
List<EntityFolder> getSystemFolders(long account);
|
||||
|
||||
@Query("SELECT * FROM folder WHERE id = :id")
|
||||
EntityFolder getFolder(Long id);
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ import androidx.core.content.ContextCompat;
|
|||
import androidx.cursoradapter.widget.SimpleCursorAdapter;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -1347,8 +1348,9 @@ public class FragmentCompose extends FragmentEx {
|
|||
|
||||
final DB db = DB.getInstance(getContext());
|
||||
|
||||
db.account().liveAccounts(true).removeObservers(getViewLifecycleOwner());
|
||||
db.account().liveAccounts(true).observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() {
|
||||
private LiveData<List<EntityIdentity>> liveIdentities = null;
|
||||
|
||||
@Override
|
||||
public void onChanged(List<EntityAccount> accounts) {
|
||||
if (accounts == null)
|
||||
|
@ -1374,8 +1376,12 @@ public class FragmentCompose extends FragmentEx {
|
|||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
EntityAccount account = (EntityAccount) parent.getAdapter().getItem(position);
|
||||
|
||||
db.identity().liveIdentities(account.id, true).removeObservers(getViewLifecycleOwner());
|
||||
db.identity().liveIdentities(account.id, true).observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() {
|
||||
if (liveIdentities == null)
|
||||
liveIdentities = db.identity().liveIdentities(account.id, true);
|
||||
else
|
||||
liveIdentities.removeObservers(getViewLifecycleOwner());
|
||||
|
||||
liveIdentities.observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<EntityIdentity> identities) {
|
||||
if (identities == null)
|
||||
|
@ -1449,7 +1455,6 @@ public class FragmentCompose extends FragmentEx {
|
|||
}
|
||||
});
|
||||
|
||||
db.attachment().liveAttachments(result.draft.id).removeObservers(getViewLifecycleOwner());
|
||||
db.attachment().liveAttachments(result.draft.id).observe(getViewLifecycleOwner(),
|
||||
new Observer<List<EntityAttachment>>() {
|
||||
@Override
|
||||
|
@ -1462,7 +1467,6 @@ public class FragmentCompose extends FragmentEx {
|
|||
}
|
||||
});
|
||||
|
||||
db.message().liveMessage(result.draft.id).removeObservers(getViewLifecycleOwner());
|
||||
db.message().liveMessage(result.draft.id).observe(getViewLifecycleOwner(), new Observer<EntityMessage>() {
|
||||
@Override
|
||||
public void onChanged(final EntityMessage draft) {
|
||||
|
|
|
@ -202,6 +202,7 @@ public class FragmentMessages extends FragmentEx {
|
|||
Bundle args = new Bundle();
|
||||
args.putLong("account", account);
|
||||
args.putLong("folder", folder);
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onLoad(Context context, Bundle args) {
|
||||
|
|
|
@ -124,6 +124,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.LifecycleService;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||
|
@ -1075,94 +1076,111 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
|
||||
// Observe operations
|
||||
Handler handler = new Handler(getMainLooper()) {
|
||||
private List<Long> handling = new ArrayList<>();
|
||||
private final PowerManager.WakeLock wlFolder = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":folder." + folder.id);
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
private LiveData<List<EntityOperation>> liveOperations;
|
||||
|
||||
@Override
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
Log.i(Helper.TAG, folder.name + " observe=" + msg.what);
|
||||
if (msg.what == 0)
|
||||
db.operation().liveOperations(folder.id).removeObservers(ServiceSynchronize.this);
|
||||
else
|
||||
db.operation().liveOperations(folder.id).observe(ServiceSynchronize.this, new Observer<List<EntityOperation>>() {
|
||||
@Override
|
||||
public void onChanged(List<EntityOperation> operations) {
|
||||
boolean process = false;
|
||||
List<Long> current = new ArrayList<>();
|
||||
for (EntityOperation op : operations) {
|
||||
if (!handling.contains(op.id))
|
||||
process = true;
|
||||
current.add(op.id);
|
||||
}
|
||||
handling = current;
|
||||
Log.i(Helper.TAG, account.name + "/" + folder.name + " observe=" + msg.what);
|
||||
try {
|
||||
if (msg.what == 0)
|
||||
liveOperations.removeObserver(observer);
|
||||
else {
|
||||
liveOperations = db.operation().liveOperations(folder.id);
|
||||
liveOperations.observe(ServiceSynchronize.this, observer);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
|
||||
if (handling.size() > 0 && process) {
|
||||
Log.i(Helper.TAG, folder.name + " operations=" + operations.size());
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wlFolder.acquire();
|
||||
Log.i(Helper.TAG, folder.name + " process");
|
||||
private Observer<List<EntityOperation>> observer = new Observer<List<EntityOperation>>() {
|
||||
private List<Long> handling = new ArrayList<>();
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
private final PowerManager.WakeLock wlFolder = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":folder." + folder.id);
|
||||
|
||||
// Get folder
|
||||
IMAPFolder ifolder = null;
|
||||
for (EntityFolder f : folders.keySet())
|
||||
if (f.id.equals(folder.id)) {
|
||||
ifolder = folders.get(f); // null when polling
|
||||
break;
|
||||
}
|
||||
@Override
|
||||
public void onChanged(List<EntityOperation> operations) {
|
||||
boolean process = false;
|
||||
List<Long> current = new ArrayList<>();
|
||||
for (EntityOperation op : operations) {
|
||||
if (!handling.contains(op.id))
|
||||
process = true;
|
||||
current.add(op.id);
|
||||
}
|
||||
handling = current;
|
||||
|
||||
final boolean shouldClose = (ifolder == null);
|
||||
if (handling.size() > 0 && process) {
|
||||
Log.i(Helper.TAG, folder.name + " operations=" + operations.size());
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wlFolder.acquire();
|
||||
Log.i(Helper.TAG, folder.name + " process");
|
||||
|
||||
try {
|
||||
Log.i(Helper.TAG, folder.name + " run " + (shouldClose ? "offline" : "online"));
|
||||
// Get folder
|
||||
IMAPFolder ifolder = null;
|
||||
for (EntityFolder f : folders.keySet())
|
||||
if (f.id.equals(folder.id)) {
|
||||
ifolder = folders.get(f); // null when polling
|
||||
break;
|
||||
}
|
||||
|
||||
if (ifolder == null) {
|
||||
// Prevent unnecessary folder connections
|
||||
if (db.operation().getOperationCount(folder.id, null) == 0)
|
||||
return;
|
||||
final boolean shouldClose = (ifolder == null);
|
||||
|
||||
db.folder().setFolderState(folder.id, "connecting");
|
||||
try {
|
||||
Log.i(Helper.TAG, folder.name + " run " + (shouldClose ? "offline" : "online"));
|
||||
|
||||
ifolder = (IMAPFolder) istore.getFolder(folder.name);
|
||||
ifolder.open(Folder.READ_WRITE);
|
||||
if (ifolder == null) {
|
||||
// Prevent unnecessary folder connections
|
||||
if (db.operation().getOperationCount(folder.id, null) == 0)
|
||||
return;
|
||||
|
||||
db.folder().setFolderState(folder.id, "connected");
|
||||
db.folder().setFolderError(folder.id, null);
|
||||
}
|
||||
db.folder().setFolderState(folder.id, "connecting");
|
||||
|
||||
processOperations(account, folder, isession, istore, ifolder, state);
|
||||
ifolder = (IMAPFolder) istore.getFolder(folder.name);
|
||||
ifolder.open(Folder.READ_WRITE);
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
reportError(account, folder, ex);
|
||||
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
|
||||
state.error();
|
||||
} finally {
|
||||
if (shouldClose) {
|
||||
if (ifolder != null && ifolder.isOpen()) {
|
||||
db.folder().setFolderState(folder.id, "closing");
|
||||
try {
|
||||
ifolder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
db.folder().setFolderState(folder.id, "connected");
|
||||
db.folder().setFolderError(folder.id, null);
|
||||
}
|
||||
|
||||
processOperations(account, folder, isession, istore, ifolder, state);
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
reportError(account, folder, ex);
|
||||
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
|
||||
state.error();
|
||||
} finally {
|
||||
if (shouldClose) {
|
||||
if (ifolder != null && ifolder.isOpen()) {
|
||||
db.folder().setFolderState(folder.id, "closing");
|
||||
try {
|
||||
ifolder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
wlFolder.release();
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
wlFolder.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
boolean eq = super.equals(obj);
|
||||
Log.i(Helper.TAG, account.name + "/" + folder.name + " equal=" + eq + " observer=" + observer + " other=" + obj);
|
||||
return eq;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Start watching for operations
|
||||
|
@ -2423,60 +2441,63 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
db.folder().setFolderError(outbox.id, null);
|
||||
|
||||
handler = new Handler(Looper.getMainLooper()) {
|
||||
private LiveData<List<EntityOperation>> liveOperations;
|
||||
|
||||
@Override
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
Log.i(Helper.TAG, outbox.name + " observe=" + msg.what);
|
||||
|
||||
if (msg.what == 0)
|
||||
db.operation().liveOperations(outbox.id).removeObservers(ServiceSynchronize.this);
|
||||
liveOperations.removeObserver(observer);
|
||||
else {
|
||||
db.operation().liveOperations(outbox.id).observe(ServiceSynchronize.this, new Observer<List<EntityOperation>>() {
|
||||
private List<Long> handling = new ArrayList<>();
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
|
||||
@Override
|
||||
public void onChanged(List<EntityOperation> operations) {
|
||||
boolean process = false;
|
||||
List<Long> current = new ArrayList<>();
|
||||
for (EntityOperation op : operations) {
|
||||
if (!handling.contains(op.id))
|
||||
process = true;
|
||||
current.add(op.id);
|
||||
}
|
||||
handling = current;
|
||||
|
||||
if (handling.size() > 0 && process) {
|
||||
Log.i(Helper.TAG, outbox.name + " operations=" + operations.size());
|
||||
executor.submit(new Runnable() {
|
||||
PowerManager pm = getSystemService(PowerManager.class);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":outbox");
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wl.acquire();
|
||||
Log.i(Helper.TAG, outbox.name + " process");
|
||||
|
||||
db.folder().setFolderSyncState(outbox.id, "syncing");
|
||||
processOperations(null, outbox, null, null, null, state);
|
||||
db.folder().setFolderError(outbox.id, null);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, outbox.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
reportError(null, outbox, ex);
|
||||
db.folder().setFolderError(outbox.id, Helper.formatThrowable(ex));
|
||||
} finally {
|
||||
db.folder().setFolderSyncState(outbox.id, null);
|
||||
wl.release();
|
||||
EntityLog.log(ServiceSynchronize.this, "Outbox wake lock=" + wl.isHeld());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
liveOperations = db.operation().liveOperations(outbox.id);
|
||||
liveOperations.observe(ServiceSynchronize.this, observer);
|
||||
}
|
||||
}
|
||||
|
||||
private Observer<List<EntityOperation>> observer = new Observer<List<EntityOperation>>() {
|
||||
private List<Long> handling = new ArrayList<>();
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
PowerManager pm = getSystemService(PowerManager.class);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":outbox");
|
||||
|
||||
@Override
|
||||
public void onChanged(List<EntityOperation> operations) {
|
||||
boolean process = false;
|
||||
List<Long> current = new ArrayList<>();
|
||||
for (EntityOperation op : operations) {
|
||||
if (!handling.contains(op.id))
|
||||
process = true;
|
||||
current.add(op.id);
|
||||
}
|
||||
handling = current;
|
||||
|
||||
if (handling.size() > 0 && process) {
|
||||
Log.i(Helper.TAG, outbox.name + " operations=" + operations.size());
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wl.acquire();
|
||||
Log.i(Helper.TAG, outbox.name + " process");
|
||||
|
||||
db.folder().setFolderSyncState(outbox.id, "syncing");
|
||||
processOperations(null, outbox, null, null, null, state);
|
||||
db.folder().setFolderError(outbox.id, null);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(Helper.TAG, outbox.name + " " + ex + "\n" + Log.getStackTraceString(ex));
|
||||
reportError(null, outbox, ex);
|
||||
db.folder().setFolderError(outbox.id, Helper.formatThrowable(ex));
|
||||
} finally {
|
||||
db.folder().setFolderSyncState(outbox.id, null);
|
||||
wl.release();
|
||||
EntityLog.log(ServiceSynchronize.this, "Outbox wake lock=" + wl.isHeld());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
handler.sendEmptyMessage(1);
|
||||
db.folder().setFolderState(outbox.id, "connected");
|
||||
|
|
|
@ -31,11 +31,13 @@ import android.util.Log;
|
|||
import java.util.List;
|
||||
|
||||
import androidx.lifecycle.LifecycleService;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class ServiceTileUnseen extends TileService {
|
||||
LifecycleService owner = new LifecycleService();
|
||||
private LifecycleService owner = new LifecycleService();
|
||||
private LiveData<List<TupleMessageEx>> liveMessages;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
@ -63,9 +65,8 @@ public class ServiceTileUnseen extends TileService {
|
|||
|
||||
public void onStartListening() {
|
||||
Log.i(Helper.TAG, "Start tile unseen");
|
||||
|
||||
DB db = DB.getInstance(this);
|
||||
db.message().liveUnseenUnified().observe(owner, new Observer<List<TupleMessageEx>>() {
|
||||
liveMessages = DB.getInstance(this).message().liveUnseenUnified();
|
||||
liveMessages.observe(owner, new Observer<List<TupleMessageEx>>() {
|
||||
@Override
|
||||
public void onChanged(List<TupleMessageEx> messages) {
|
||||
Log.i(Helper.TAG, "Update tile unseen=" + messages.size());
|
||||
|
@ -85,9 +86,8 @@ public class ServiceTileUnseen extends TileService {
|
|||
|
||||
public void onStopListening() {
|
||||
Log.i(Helper.TAG, "Stop tile unseen");
|
||||
|
||||
DB db = DB.getInstance(this);
|
||||
db.message().liveUnseenUnified().removeObservers(owner);
|
||||
if (liveMessages != null)
|
||||
liveMessages.removeObservers(owner);
|
||||
}
|
||||
|
||||
public void onClick() {
|
||||
|
|
Loading…
Reference in New Issue