Fixed multiple observers

pull/146/head
M66B 7 years ago
parent 3aa89cae97
commit c4733427ae

@ -96,6 +96,7 @@ import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.paging.AsyncPagedListDiffer; import androidx.paging.AsyncPagedListDiffer;
@ -188,6 +189,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
private Group grpAttachments; private Group grpAttachments;
private Group grpExpanded; private Group grpExpanded;
private LiveData<List<EntityAttachment>> liveAttachments = null;
private Observer<List<EntityAttachment>> observerAttachments = null;
ViewHolder(View itemView) { ViewHolder(View itemView) {
super(itemView); super(itemView);
@ -400,10 +404,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} }
if (debug) { 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 + String text = message.error +
"\n" + message.uid + "/" + message.id + " " + df.format(new Date(message.received)) + "\n" + message.uid + "/" + message.id + " " + df.format(new Date(message.received)) +
"\n" + (message.ui_hide ? "HIDDEN " : "") + "\n" + (message.ui_hide ? "HIDDEN " : "") +
@ -411,14 +411,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
" found=" + message.ui_found + " found=" + message.ui_found +
"\n" + message.msgid + "\n" + message.msgid +
"\n" + message.thread; "\n" + message.thread;
if (operations != null)
for (EntityOperation op : operations)
text += "\n" + op.id + ":" + op.name + " " + df.format(new Date(op.created));
tvError.setText(text); tvError.setText(text);
tvError.setVisibility(View.VISIBLE); tvError.setVisibility(View.VISIBLE);
}
});
} else { } else {
tvError.setText(message.error); tvError.setText(message.error);
tvError.setVisibility(message.error == null ? View.GONE : View.VISIBLE); 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); grpAttachments.setVisibility(message.attachments > 0 && show_expanded ? View.VISIBLE : View.GONE);
grpExpanded.setVisibility(viewType == ViewType.THREAD && 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); bnvActions.setTag(null);
if (show_expanded) { if (show_expanded) {
@ -488,9 +480,18 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
bodyTask.load(context, owner, args); 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 @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 hasJunk = false;
boolean hasTrash = false; boolean hasTrash = false;
boolean hasArchive = false; boolean hasArchive = false;
@ -524,11 +525,15 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
bnvActions.setVisibility(View.VISIBLE); bnvActions.setVisibility(View.VISIBLE);
vSeparatorBody.setVisibility(View.GONE); vSeparatorBody.setVisibility(View.GONE);
} }
});
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(context, owner, ex);
}
}.load(context, owner, sargs);
// Observe attachments // Observe attachments
db.attachment().liveAttachments(message.id).observe(owner, observerAttachments = new Observer<List<EntityAttachment>>() {
new Observer<List<EntityAttachment>>() {
@Override @Override
public void onChanged(@Nullable List<EntityAttachment> attachments) { public void onChanged(@Nullable List<EntityAttachment> attachments) {
if (attachments == null) if (attachments == null)
@ -542,12 +547,21 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
bodyTask.load(context, owner, args); bodyTask.load(context, owner, args);
} }
} }
}); };
liveAttachments = db.attachment().liveAttachments(message.id);
liveAttachments.observe(owner, observerAttachments);
} }
itemView.setActivated(selectionTracker != null && selectionTracker.isSelected(message.id)); itemView.setActivated(selectionTracker != null && selectionTracker.isSelected(message.id));
} }
void unbind() {
if (liveAttachments != null) {
liveAttachments.removeObserver(observerAttachments);
liveAttachments = null;
}
}
@Override @Override
public void onClick(View view) { public void onClick(View view) {
int pos = getAdapterPosition(); int pos = getAdapterPosition();
@ -1040,10 +1054,14 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} }
private void onAnswer(final ActionData data) { private void onAnswer(final ActionData data) {
final DB db = DB.getInstance(context); new SimpleTask<List<EntityAnswer>>() {
db.answer().liveAnswers().observe(owner, new Observer<List<EntityAnswer>>() { @Override
protected List<EntityAnswer> onLoad(Context context, Bundle args) {
return DB.getInstance(context).answer().getAnswers();
}
@Override @Override
public void onChanged(List<EntityAnswer> answers) { protected void onLoaded(Bundle args, List<EntityAnswer> answers) {
if (answers == null || answers.size() == 0) { if (answers == null || answers.size() == 0) {
Snackbar snackbar = Snackbar.make( Snackbar snackbar = Snackbar.make(
itemView, itemView,
@ -1094,10 +1112,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
popupMenu.show(); 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) { private void onUnseen(final ActionData data) {
@ -1616,6 +1637,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
@Override @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) { public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unbind();
holder.unwire(); holder.unwire();
TupleMessageEx message = differ.getItem(position); 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) { void setSelectionTracker(SelectionTracker<Long> selectionTracker) {
this.selectionTracker = selectionTracker; this.selectionTracker = selectionTracker;
} }

@ -97,6 +97,11 @@ public interface DaoFolder {
@Query("SELECT * FROM folder ORDER BY account, name") @Query("SELECT * FROM folder ORDER BY account, name")
List<EntityFolder> getFolders(); 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") @Query("SELECT * FROM folder WHERE id = :id")
EntityFolder getFolder(Long id); EntityFolder getFolder(Long id);

@ -105,6 +105,7 @@ import androidx.core.content.ContextCompat;
import androidx.cursoradapter.widget.SimpleCursorAdapter; import androidx.cursoradapter.widget.SimpleCursorAdapter;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -1347,8 +1348,9 @@ public class FragmentCompose extends FragmentEx {
final DB db = DB.getInstance(getContext()); final DB db = DB.getInstance(getContext());
db.account().liveAccounts(true).removeObservers(getViewLifecycleOwner());
db.account().liveAccounts(true).observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() { db.account().liveAccounts(true).observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() {
private LiveData<List<EntityIdentity>> liveIdentities = null;
@Override @Override
public void onChanged(List<EntityAccount> accounts) { public void onChanged(List<EntityAccount> accounts) {
if (accounts == null) if (accounts == null)
@ -1374,8 +1376,12 @@ public class FragmentCompose extends FragmentEx {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
EntityAccount account = (EntityAccount) parent.getAdapter().getItem(position); EntityAccount account = (EntityAccount) parent.getAdapter().getItem(position);
db.identity().liveIdentities(account.id, true).removeObservers(getViewLifecycleOwner()); if (liveIdentities == null)
db.identity().liveIdentities(account.id, true).observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() { liveIdentities = db.identity().liveIdentities(account.id, true);
else
liveIdentities.removeObservers(getViewLifecycleOwner());
liveIdentities.observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() {
@Override @Override
public void onChanged(@Nullable List<EntityIdentity> identities) { public void onChanged(@Nullable List<EntityIdentity> identities) {
if (identities == null) 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(), db.attachment().liveAttachments(result.draft.id).observe(getViewLifecycleOwner(),
new Observer<List<EntityAttachment>>() { new Observer<List<EntityAttachment>>() {
@Override @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>() { db.message().liveMessage(result.draft.id).observe(getViewLifecycleOwner(), new Observer<EntityMessage>() {
@Override @Override
public void onChanged(final EntityMessage draft) { public void onChanged(final EntityMessage draft) {

@ -202,6 +202,7 @@ public class FragmentMessages extends FragmentEx {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("account", account); args.putLong("account", account);
args.putLong("folder", folder); args.putLong("folder", folder);
new SimpleTask<Void>() { new SimpleTask<Void>() {
@Override @Override
protected Void onLoad(Context context, Bundle args) { protected Void onLoad(Context context, Bundle args) {

@ -124,6 +124,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleService; import androidx.lifecycle.LifecycleService;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
@ -1075,18 +1076,29 @@ public class ServiceSynchronize extends LifecycleService {
// Observe operations // Observe operations
Handler handler = new Handler(getMainLooper()) { Handler handler = new Handler(getMainLooper()) {
private List<Long> handling = new ArrayList<>(); private LiveData<List<EntityOperation>> liveOperations;
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);
@Override @Override
public void handleMessage(android.os.Message msg) { public void handleMessage(android.os.Message msg) {
Log.i(Helper.TAG, folder.name + " observe=" + msg.what); Log.i(Helper.TAG, account.name + "/" + folder.name + " observe=" + msg.what);
try {
if (msg.what == 0) if (msg.what == 0)
db.operation().liveOperations(folder.id).removeObservers(ServiceSynchronize.this); liveOperations.removeObserver(observer);
else else {
db.operation().liveOperations(folder.id).observe(ServiceSynchronize.this, new Observer<List<EntityOperation>>() { liveOperations = db.operation().liveOperations(folder.id);
liveOperations.observe(ServiceSynchronize.this, observer);
}
} catch (Throwable ex) {
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
}
}
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);
@Override @Override
public void onChanged(List<EntityOperation> operations) { public void onChanged(List<EntityOperation> operations) {
boolean process = false; boolean process = false;
@ -1161,9 +1173,15 @@ public class ServiceSynchronize extends LifecycleService {
}); });
} }
} }
});
@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 // Start watching for operations
handler.sendEmptyMessage(1); handler.sendEmptyMessage(1);
@ -2423,16 +2441,25 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderError(outbox.id, null); db.folder().setFolderError(outbox.id, null);
handler = new Handler(Looper.getMainLooper()) { handler = new Handler(Looper.getMainLooper()) {
private LiveData<List<EntityOperation>> liveOperations;
@Override @Override
public void handleMessage(android.os.Message msg) { public void handleMessage(android.os.Message msg) {
Log.i(Helper.TAG, outbox.name + " observe=" + msg.what); Log.i(Helper.TAG, outbox.name + " observe=" + msg.what);
if (msg.what == 0) if (msg.what == 0)
db.operation().liveOperations(outbox.id).removeObservers(ServiceSynchronize.this); liveOperations.removeObserver(observer);
else { else {
db.operation().liveOperations(outbox.id).observe(ServiceSynchronize.this, new Observer<List<EntityOperation>>() { 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 List<Long> handling = new ArrayList<>();
private ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory); 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 @Override
public void onChanged(List<EntityOperation> operations) { public void onChanged(List<EntityOperation> operations) {
@ -2448,10 +2475,6 @@ public class ServiceSynchronize extends LifecycleService {
if (handling.size() > 0 && process) { if (handling.size() > 0 && process) {
Log.i(Helper.TAG, outbox.name + " operations=" + operations.size()); Log.i(Helper.TAG, outbox.name + " operations=" + operations.size());
executor.submit(new Runnable() { executor.submit(new Runnable() {
PowerManager pm = getSystemService(PowerManager.class);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":outbox");
@Override @Override
public void run() { public void run() {
try { try {
@ -2474,9 +2497,7 @@ public class ServiceSynchronize extends LifecycleService {
}); });
} }
} }
}); };
}
}
}; };
handler.sendEmptyMessage(1); handler.sendEmptyMessage(1);
db.folder().setFolderState(outbox.id, "connected"); db.folder().setFolderState(outbox.id, "connected");

@ -31,11 +31,13 @@ import android.util.Log;
import java.util.List; import java.util.List;
import androidx.lifecycle.LifecycleService; import androidx.lifecycle.LifecycleService;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
@TargetApi(Build.VERSION_CODES.N) @TargetApi(Build.VERSION_CODES.N)
public class ServiceTileUnseen extends TileService { public class ServiceTileUnseen extends TileService {
LifecycleService owner = new LifecycleService(); private LifecycleService owner = new LifecycleService();
private LiveData<List<TupleMessageEx>> liveMessages;
@Override @Override
public void onCreate() { public void onCreate() {
@ -63,9 +65,8 @@ public class ServiceTileUnseen extends TileService {
public void onStartListening() { public void onStartListening() {
Log.i(Helper.TAG, "Start tile unseen"); Log.i(Helper.TAG, "Start tile unseen");
liveMessages = DB.getInstance(this).message().liveUnseenUnified();
DB db = DB.getInstance(this); liveMessages.observe(owner, new Observer<List<TupleMessageEx>>() {
db.message().liveUnseenUnified().observe(owner, new Observer<List<TupleMessageEx>>() {
@Override @Override
public void onChanged(List<TupleMessageEx> messages) { public void onChanged(List<TupleMessageEx> messages) {
Log.i(Helper.TAG, "Update tile unseen=" + messages.size()); Log.i(Helper.TAG, "Update tile unseen=" + messages.size());
@ -85,9 +86,8 @@ public class ServiceTileUnseen extends TileService {
public void onStopListening() { public void onStopListening() {
Log.i(Helper.TAG, "Stop tile unseen"); Log.i(Helper.TAG, "Stop tile unseen");
if (liveMessages != null)
DB db = DB.getInstance(this); liveMessages.removeObservers(owner);
db.message().liveUnseenUnified().removeObservers(owner);
} }
public void onClick() { public void onClick() {

Loading…
Cancel
Save