refactor ListenableFutureTask and make saves async

// FREEBIE
This commit is contained in:
Jake McGinty 2014-10-28 02:23:00 -05:00
parent 53da1f849a
commit ff2ac8a66e
8 changed files with 107 additions and 54 deletions

View File

@ -1,32 +1,30 @@
package org.whispersystems.textsecure.util;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ListenableFutureTask<V> extends FutureTask<V> {
// private WeakReference<FutureTaskListener<V>> listener;
private FutureTaskListener<V> listener;
private final List<FutureTaskListener<V>> listeners;
public ListenableFutureTask(Callable<V> callable, FutureTaskListener<V> listener) {
public ListenableFutureTask(Callable<V> callable) {
super(callable);
this.listener = listener;
// if (listener == null) {
// this.listener = null;
// } else {
// this.listener = new WeakReference<FutureTaskListener<V>>(listener);
// }
this.listeners = new LinkedList<>();
}
public synchronized void setListener(FutureTaskListener<V> listener) {
// if (listener != null) this.listener = new WeakReference<FutureTaskListener<V>>(listener);
// else this.listener = null;
this.listener = listener;
public synchronized void addListener(FutureTaskListener<V> listener) {
if (this.isDone()) {
callback();
callback(listener);
return;
}
listeners.add(listener);
}
public synchronized boolean removeListener(FutureTaskListener<V> listener) {
return listeners.remove(listener);
}
@Override
@ -35,17 +33,19 @@ public class ListenableFutureTask<V> extends FutureTask<V> {
}
private void callback() {
if (this.listener != null) {
FutureTaskListener<V> nestedListener = this.listener;
// FutureTaskListener<V> nestedListener = this.listener.get();
if (nestedListener != null) {
try {
nestedListener.onSuccess(get());
} catch (ExecutionException ee) {
nestedListener.onFailure(ee);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
for (FutureTaskListener<V> listener : listeners) {
callback(listener);
}
}
private void callback(FutureTaskListener<V> listener) {
if (listener != null) {
try {
listener.onSuccess(get());
} catch (ExecutionException ee) {
listener.onFailure(ee);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
}

View File

@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.util.FutureTaskListener;
import java.sql.Date;
import java.text.SimpleDateFormat;
@ -242,14 +243,20 @@ public class ConversationFragment extends SherlockListFragment
SaveAttachmentTask.showWarningDialog(getActivity(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final Slide slide = message.getMediaSlideSync();
if (slide == null) {
Log.w(TAG, "No slide with attachable media found, failing nicely.");
Toast.makeText(getActivity(), R.string.ConversationFragment_error_while_saving_attachment_to_sd_card, Toast.LENGTH_LONG).show();
return;
}
SaveAttachmentTask saveTask = new SaveAttachmentTask(getActivity(), masterSecret);
saveTask.execute(new Attachment(slide.getUri(), slide.getContentType(), message.getDateReceived()));
message.fetchMediaSlide(new FutureTaskListener<Slide>() {
@Override
public void onSuccess(Slide slide) {
SaveAttachmentTask saveTask = new SaveAttachmentTask(getActivity(), masterSecret);
saveTask.execute(new Attachment(slide.getUri(), slide.getContentType(), message.getDateReceived()));
}
@Override
public void onFailure(Throwable error) {
Log.w(TAG, "No slide with attachable media found, failing nicely.");
Log.w(TAG, error);
Toast.makeText(getActivity(), R.string.ConversationFragment_error_while_saving_attachment_to_sd_card, Toast.LENGTH_LONG).show();
}
});
}
});
}

View File

@ -107,6 +107,7 @@ public class ConversationItem extends LinearLayout {
private Button mmsDownloadButton;
private TextView mmsDownloadingLabel;
private ListenableFutureTask<SlideDeck> slideDeck;
private FutureTaskListener<SlideDeck> slideDeckListener;
private TypedArray backgroundDrawables;
private final FailedIconClickListener failedIconClickListener = new FailedIconClickListener();
@ -181,8 +182,8 @@ public class ConversationItem extends LinearLayout {
}
public void unbind() {
if (slideDeck != null)
slideDeck.setListener(null);
if (slideDeck != null && slideDeckListener != null)
slideDeck.removeListener(slideDeckListener);
}
public MessageRecord getMessageRecord() {
@ -345,7 +346,7 @@ public class ConversationItem extends LinearLayout {
}
slideDeck = messageRecord.getSlideDeckFuture();
slideDeck.setListener(new FutureTaskListener<SlideDeck>() {
slideDeckListener = new FutureTaskListener<SlideDeck>() {
@Override
public void onSuccess(final SlideDeck result) {
if (result == null)
@ -376,7 +377,8 @@ public class ConversationItem extends LinearLayout {
@Override
public void onFailure(Throwable error) {}
});
};
slideDeck.addListener(slideDeckListener);
}
/// Helper Methods

View File

@ -1064,7 +1064,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
}
};
future = new ListenableFutureTask<SlideDeck>(task, null);
future = new ListenableFutureTask<SlideDeck>(task);
slideResolver.execute(future);
return future;
@ -1084,7 +1084,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
}
};
ListenableFutureTask<SlideDeck> future = new ListenableFutureTask<SlideDeck>(task, null);
ListenableFutureTask<SlideDeck> future = new ListenableFutureTask<SlideDeck>(task);
future.run();
return future;

View File

@ -22,10 +22,13 @@ import android.util.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.mms.MediaNotFoundException;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.whispersystems.textsecure.push.exceptions.NotFoundException;
import org.whispersystems.textsecure.util.FutureTaskListener;
import org.whispersystems.textsecure.util.ListenableFutureTask;
import java.util.List;
@ -82,21 +85,26 @@ public class MediaMmsMessageRecord extends MessageRecord {
return deck != null && deck.containsMediaSlide();
}
public Slide getMediaSlideSync() {
SlideDeck deck = getSlideDeckSync();
if (deck == null) {
return null;
}
List<Slide> slides = deck.getSlides();
for (Slide slide : slides) {
if (slide.hasImage() || slide.hasVideo() || slide.hasAudio()) {
return slide;
public void fetchMediaSlide(final FutureTaskListener<Slide> listener) {
slideDeckFutureTask.addListener(new FutureTaskListener<SlideDeck>() {
@Override
public void onSuccess(SlideDeck deck) {
for (Slide slide : deck.getSlides()) {
if (slide.hasImage() || slide.hasVideo() || slide.hasAudio()) {
listener.onSuccess(slide);
return;
}
}
listener.onFailure(new MediaNotFoundException("no media slide found"));
}
}
return null;
}
@Override
public void onFailure(Throwable error) {
listener.onFailure(error);
}
});
}
public int getPartCount() {
return partCount;

View File

@ -0,0 +1,36 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.mms;
public class MediaNotFoundException extends Exception {
public MediaNotFoundException() {
}
public MediaNotFoundException(String detailMessage) {
super(detailMessage);
}
public MediaNotFoundException(Throwable throwable) {
super(throwable);
}
public MediaNotFoundException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}

View File

@ -67,7 +67,7 @@ public class Recipient implements Parcelable, CanonicalRecipient {
this.contactPhoto = contactPhoto;
this.recipientId = recipientId;
future.setListener(new FutureTaskListener<RecipientDetails>() {
future.addListener(new FutureTaskListener<RecipientDetails>() {
@Override
public void onSuccess(RecipientDetails result) {
if (result != null) {

View File

@ -105,7 +105,7 @@ public class RecipientProvider {
}
};
ListenableFutureTask<RecipientDetails> future = new ListenableFutureTask<RecipientDetails>(task, null);
ListenableFutureTask<RecipientDetails> future = new ListenableFutureTask<RecipientDetails>(task);
asyncRecipientResolver.submit(future);