mirror of
https://github.com/M66B/FairEmail.git
synced 2025-02-23 22:51:02 +00:00
Close boundary on destroy
This commit is contained in:
parent
e09bd95cc6
commit
47da32aa97
3 changed files with 84 additions and 82 deletions
|
@ -71,15 +71,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
private Handler handler;
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
|
||||
private boolean destroyed = false;
|
||||
private boolean error = false;
|
||||
private int index = 0;
|
||||
|
||||
private List<Long> messages = null;
|
||||
|
||||
private MailService iservice = null;
|
||||
private IMAPFolder ifolder = null;
|
||||
private Message[] imessages = null;
|
||||
private State state;
|
||||
|
||||
interface IBoundaryCallbackMessages {
|
||||
void onLoading();
|
||||
|
@ -100,11 +92,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
void setCallback(IBoundaryCallbackMessages intf) {
|
||||
this.handler = new Handler();
|
||||
this.intf = intf;
|
||||
|
||||
if (imessages == null)
|
||||
index = 0;
|
||||
else
|
||||
index = imessages.length - 1;
|
||||
this.state = new State();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,19 +102,21 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onItemAtEndLoaded(final TupleMessageEx itemAtEnd) {
|
||||
public void onItemAtEndLoaded(@NonNull final TupleMessageEx itemAtEnd) {
|
||||
Log.i("Boundary at end");
|
||||
queue_load(false);
|
||||
}
|
||||
|
||||
private void queue_load(final boolean zero) {
|
||||
final State state = this.state;
|
||||
|
||||
executor.submit(new Runnable() {
|
||||
private int fetched;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (destroyed || error)
|
||||
if (state.destroyed || state.error)
|
||||
return;
|
||||
|
||||
fetched = 0;
|
||||
|
@ -138,9 +128,9 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
}
|
||||
});
|
||||
if (server)
|
||||
fetched = load_server();
|
||||
fetched = load_server(state);
|
||||
else
|
||||
fetched = load_device();
|
||||
fetched = load_device(state);
|
||||
} catch (final Throwable ex) {
|
||||
Log.e("Boundary", ex);
|
||||
if (intf != null)
|
||||
|
@ -163,12 +153,12 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
});
|
||||
}
|
||||
|
||||
private int load_device() {
|
||||
private int load_device(State state) {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
if (messages == null) {
|
||||
messages = db.message().getMessageIdsByFolder(folder);
|
||||
Log.i("Boundary device folder=" + folder + " query=" + query + " messages=" + messages.size());
|
||||
if (state.messages == null) {
|
||||
state.messages = db.message().getMessageIdsByFolder(folder);
|
||||
Log.i("Boundary device folder=" + folder + " query=" + query + " messages=" + state.messages.size());
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
|
@ -176,10 +166,10 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
db.beginTransaction();
|
||||
|
||||
String find = (TextUtils.isEmpty(query) ? null : query.toLowerCase());
|
||||
for (int i = index; i < messages.size() && found < pageSize && !destroyed; i++) {
|
||||
index = i + 1;
|
||||
for (int i = state.index; i < state.messages.size() && found < pageSize && !state.destroyed; i++) {
|
||||
state.index = i + 1;
|
||||
|
||||
EntityMessage message = db.message().getMessage(messages.get(i));
|
||||
EntityMessage message = db.message().getMessage(state.messages.get(i));
|
||||
if (message == null)
|
||||
continue;
|
||||
|
||||
|
@ -243,7 +233,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
return found;
|
||||
}
|
||||
|
||||
private int load_server() throws MessagingException, IOException {
|
||||
private int load_server(State state) throws MessagingException, IOException {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
final EntityFolder browsable = db.folder().getBrowsableFolder(folder, query != null);
|
||||
|
@ -254,7 +244,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
if (account == null)
|
||||
return 0;
|
||||
|
||||
if (imessages == null)
|
||||
if (state.imessages == null)
|
||||
try {
|
||||
// Check connectivity
|
||||
if (!ConnectionHelper.getNetworkState(context).isSuitable())
|
||||
|
@ -264,28 +254,28 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
boolean debug = (prefs.getBoolean("debug", false) || BuildConfig.BETA_RELEASE);
|
||||
|
||||
Log.i("Boundary server connecting account=" + account.name);
|
||||
iservice = new MailService(context, account.getProtocol(), account.realm, account.insecure, debug);
|
||||
iservice.setPartialFetch(account.partial_fetch);
|
||||
iservice.setSeparateStoreConnection();
|
||||
iservice.connect(account);
|
||||
state.iservice = new MailService(context, account.getProtocol(), account.realm, account.insecure, debug);
|
||||
state.iservice.setPartialFetch(account.partial_fetch);
|
||||
state.iservice.setSeparateStoreConnection();
|
||||
state.iservice.connect(account);
|
||||
|
||||
Log.i("Boundary server opening folder=" + browsable.name);
|
||||
ifolder = (IMAPFolder) iservice.getStore().getFolder(browsable.name);
|
||||
ifolder.open(Folder.READ_WRITE);
|
||||
state.ifolder = (IMAPFolder) state.iservice.getStore().getFolder(browsable.name);
|
||||
state.ifolder.open(Folder.READ_WRITE);
|
||||
|
||||
Log.i("Boundary server query=" + query);
|
||||
if (query == null)
|
||||
imessages = ifolder.getMessages();
|
||||
state.imessages = state.ifolder.getMessages();
|
||||
else if (query.startsWith(context.getString(R.string.title_search_special_prefix) + ":")) {
|
||||
String special = query.split(":")[1];
|
||||
if (context.getString(R.string.title_search_special_unseen).equals(special))
|
||||
imessages = ifolder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
|
||||
state.imessages = state.ifolder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
|
||||
else if (context.getString(R.string.title_search_special_flagged).equals(special))
|
||||
imessages = ifolder.search(new FlagTerm(new Flags(Flags.Flag.FLAGGED), true));
|
||||
state.imessages = state.ifolder.search(new FlagTerm(new Flags(Flags.Flag.FLAGGED), true));
|
||||
else
|
||||
imessages = new Message[0];
|
||||
state.imessages = new Message[0];
|
||||
} else {
|
||||
Object result = ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
||||
Object result = state.ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
||||
@Override
|
||||
public Object doCommand(IMAPProtocol protocol) {
|
||||
// Yahoo! does not support keyword search, but uses the flags $Forwarded $Junk $NotJunk
|
||||
|
@ -299,7 +289,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
try {
|
||||
// https://tools.ietf.org/html/rfc3501#section-6.4.4
|
||||
Argument arg = new Argument();
|
||||
if (query.startsWith("raw:") && iservice.getStore().hasCapability("X-GM-EXT-1")) {
|
||||
if (query.startsWith("raw:") && state.iservice.getStore().hasCapability("X-GM-EXT-1")) {
|
||||
// https://support.google.com/mail/answer/7190
|
||||
// https://developers.google.com/gmail/imap/imap-extensions#extension_of_the_search_command_x-gm-raw
|
||||
arg.writeAtom("X-GM-RAW");
|
||||
|
@ -342,7 +332,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
|
||||
Message[] imessages = new Message[msgnums.size()];
|
||||
for (int i = 0; i < msgnums.size(); i++)
|
||||
imessages[i] = ifolder.getMessage(msgnums.get(i));
|
||||
imessages[i] = state.ifolder.getMessage(msgnums.get(i));
|
||||
|
||||
return imessages;
|
||||
} else {
|
||||
|
@ -367,7 +357,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
term = new OrTerm(term, new FlagTerm(
|
||||
new Flags(Helper.sanitizeKeyword(search)), true));
|
||||
|
||||
return ifolder.search(term);
|
||||
return state.ifolder.search(term);
|
||||
}
|
||||
|
||||
} catch (MessagingException ex) {
|
||||
|
@ -380,13 +370,13 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
if (result instanceof MessagingException)
|
||||
throw (MessagingException) result;
|
||||
|
||||
imessages = (Message[]) result;
|
||||
state.imessages = (Message[]) result;
|
||||
}
|
||||
Log.i("Boundary server found messages=" + imessages.length);
|
||||
Log.i("Boundary server found messages=" + state.imessages.length);
|
||||
|
||||
index = imessages.length - 1;
|
||||
state.index = state.imessages.length - 1;
|
||||
} catch (Throwable ex) {
|
||||
error = true;
|
||||
state.error = true;
|
||||
if (ex instanceof FolderClosedException)
|
||||
Log.w("Search", ex);
|
||||
else
|
||||
|
@ -397,11 +387,11 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
List<EntityRule> rules = db.rule().getEnabledRules(browsable.id);
|
||||
|
||||
int found = 0;
|
||||
while (index >= 0 && found < pageSize && !destroyed) {
|
||||
Log.i("Boundary server index=" + index);
|
||||
int from = Math.max(0, index - (pageSize - found) + 1);
|
||||
Message[] isub = Arrays.copyOfRange(imessages, from, index + 1);
|
||||
index -= (pageSize - found);
|
||||
while (state.index >= 0 && found < pageSize && !state.destroyed) {
|
||||
Log.i("Boundary server index=" + state.index);
|
||||
int from = Math.max(0, state.index - (pageSize - found) + 1);
|
||||
Message[] isub = Arrays.copyOfRange(state.imessages, from, state.index + 1);
|
||||
state.index -= (pageSize - found);
|
||||
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.ENVELOPE);
|
||||
|
@ -411,20 +401,20 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
fp.add(IMAPFolder.FetchProfileItem.HEADERS);
|
||||
fp.add(FetchProfile.Item.SIZE);
|
||||
fp.add(IMAPFolder.FetchProfileItem.INTERNALDATE);
|
||||
ifolder.fetch(isub, fp);
|
||||
state.ifolder.fetch(isub, fp);
|
||||
|
||||
try {
|
||||
db.beginTransaction();
|
||||
|
||||
for (int j = isub.length - 1; j >= 0 && found < pageSize && !destroyed; j--)
|
||||
for (int j = isub.length - 1; j >= 0 && found < pageSize && !state.destroyed; j--)
|
||||
try {
|
||||
long uid = ifolder.getUID(isub[j]);
|
||||
long uid = state.ifolder.getUID(isub[j]);
|
||||
Log.i("Boundary server sync uid=" + uid);
|
||||
EntityMessage message = db.message().getMessageByUid(browsable.id, uid);
|
||||
if (message == null) {
|
||||
message = Core.synchronizeMessage(context,
|
||||
account, browsable,
|
||||
ifolder, (IMAPMessage) isub[j],
|
||||
state.ifolder, (IMAPMessage) isub[j],
|
||||
true, true,
|
||||
rules, null);
|
||||
found++;
|
||||
|
@ -457,20 +447,39 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
return found;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
destroyed = true;
|
||||
void close() {
|
||||
final State state = this.state;
|
||||
this.state = new State();
|
||||
state.destroyed = true;
|
||||
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.i("Boundary destroy");
|
||||
Log.i("Boundary close");
|
||||
try {
|
||||
if (iservice != null)
|
||||
iservice.close();
|
||||
if (state.ifolder != null)
|
||||
state.ifolder.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("Boundary", ex);
|
||||
}
|
||||
try {
|
||||
if (state.iservice != null)
|
||||
state.iservice.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("Boundary", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class State {
|
||||
boolean destroyed = false;
|
||||
boolean error = false;
|
||||
int index = 0;
|
||||
List<Long> messages = null;
|
||||
|
||||
MailService iservice = null;
|
||||
IMAPFolder ifolder = null;
|
||||
Message[] imessages = null;
|
||||
}
|
||||
}
|
|
@ -2779,7 +2779,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
|
|||
getContext(), getViewLifecycleOwner(),
|
||||
viewType, type, account, folder, thread, id, query, server);
|
||||
|
||||
vmodel.setCallback(callback);
|
||||
vmodel.setCallback(getViewLifecycleOwner(), callback);
|
||||
vmodel.setObserver(getViewLifecycleOwner(), observer);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,10 +71,8 @@ public class ViewModelMessages extends ViewModel {
|
|||
if (model == null || !model.args.equals(args)) {
|
||||
Log.i("Creating model=" + viewType + " replace=" + (model != null));
|
||||
|
||||
if (model != null) {
|
||||
if (model != null)
|
||||
model.list.removeObservers(owner);
|
||||
model.clear();
|
||||
}
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
|
@ -174,7 +172,7 @@ public class ViewModelMessages extends ViewModel {
|
|||
|
||||
if (viewType == AdapterMessage.ViewType.THREAD || lowmem) {
|
||||
Log.i("Remove model=" + viewType);
|
||||
remove(viewType);
|
||||
models.remove(viewType);
|
||||
}
|
||||
|
||||
dump();
|
||||
|
@ -182,10 +180,10 @@ public class ViewModelMessages extends ViewModel {
|
|||
});
|
||||
|
||||
if (viewType == AdapterMessage.ViewType.UNIFIED) {
|
||||
remove(AdapterMessage.ViewType.FOLDER);
|
||||
remove(AdapterMessage.ViewType.SEARCH);
|
||||
models.remove(AdapterMessage.ViewType.FOLDER);
|
||||
models.remove(AdapterMessage.ViewType.SEARCH);
|
||||
} else if (viewType == AdapterMessage.ViewType.FOLDER)
|
||||
remove(AdapterMessage.ViewType.SEARCH);
|
||||
models.remove(AdapterMessage.ViewType.SEARCH);
|
||||
|
||||
if (viewType != AdapterMessage.ViewType.THREAD) {
|
||||
last = viewType;
|
||||
|
@ -201,15 +199,7 @@ public class ViewModelMessages extends ViewModel {
|
|||
@Override
|
||||
protected void onCleared() {
|
||||
for (AdapterMessage.ViewType viewType : new ArrayList<>(models.keySet()))
|
||||
remove(viewType);
|
||||
}
|
||||
|
||||
private void remove(AdapterMessage.ViewType viewType) {
|
||||
Model model = models.get(viewType);
|
||||
if (model != null) {
|
||||
model.clear();
|
||||
models.remove(viewType);
|
||||
}
|
||||
}
|
||||
|
||||
void observePrevNext(LifecycleOwner owner, final long id, final IPrevNext intf) {
|
||||
|
@ -385,20 +375,23 @@ public class ViewModelMessages extends ViewModel {
|
|||
this.boundary = boundary;
|
||||
}
|
||||
|
||||
void setCallback(BoundaryCallbackMessages.IBoundaryCallbackMessages callback) {
|
||||
if (boundary != null)
|
||||
void setCallback(LifecycleOwner owner, BoundaryCallbackMessages.IBoundaryCallbackMessages callback) {
|
||||
if (boundary != null) {
|
||||
boundary.setCallback(callback);
|
||||
|
||||
owner.getLifecycle().addObserver(new LifecycleObserver() {
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||
public void onDestroyed() {
|
||||
boundary.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void setObserver(LifecycleOwner owner, @NonNull Observer<PagedList<TupleMessageEx>> observer) {
|
||||
//list.removeObservers(owner);
|
||||
list.observe(owner, observer);
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
if (this.boundary != null)
|
||||
this.boundary.clear();
|
||||
}
|
||||
}
|
||||
|
||||
interface IPrevNext {
|
||||
|
|
Loading…
Reference in a new issue