Skip to content

Instantly share code, notes, and snippets.

@hnakagawa
Last active August 29, 2015 14:14
Show Gist options
  • Save hnakagawa/2bf6cd0d7b0e6ba6caa9 to your computer and use it in GitHub Desktop.
Save hnakagawa/2bf6cd0d7b0e6ba6caa9 to your computer and use it in GitHub Desktop.
おれおれコールバック設計 ref: http://qiita.com/hnakagawa/items/984557b13aede61d05d0
public class CallbackHelper<T> {
private final Map<CallbackLifecycle, SparseArray<T>> mCallbacks = new WeakHashMap<>();
private final AtomicInteger mSeqId = new AtomicInteger(1);
public int getAndIncrementSeq() {
return mSeqId.getAndIncrement();
}
public synchronized T getAndRemove(CallbackLifecycle lifecycle, int seq) {
if (lifecycle == null)
return null;
SparseArray<T> arr = mCallbacks.get(lifecycle);
if (arr == null)
return null;
T callback = arr.get(seq);
arr.remove(seq);
if (arr.size() == 0)
mCallbacks.remove(lifecycle);
return callback;
}
public synchronized void put(CallbackLifecycle lifecycle, T callback, int seq) {
if (lifecycle == null || callback == null)
return;
SparseArray<T> arr = mCallbacks.get(lifecycle);
if (arr == null) {
arr = new SparseArray<T>();
mCallbacks.put(lifecycle, arr);
}
arr.put(seq, callback);
}
public synchronized void remove(CallbackLifecycle lifecycle) {
if (lifecycle == null)
return;
mCallbacks.remove(lifecycle);
}
}
public class ExampleActivity extends Activity implements CallbackLifecycle, View.OnClickListener {
//省略
@Override
protected void onDestroy() {
mMessageManager.removeCallbackFor(this); //ライフサイクルオブジェクトに結びついたCallbackを一括削除
super.onDestroy();
}
@Override
public void onClick(View v) {
mMessageManager.send(this, getMessageFromView(), new Callback<Result>() {
@Override
public void done(Result result) {
//do something...
}
@Override
public void error(Exception exception) {
//do something...
}
});
}
//省略
}
public class MessageManager {
private final ThreadPool mThreadPool = new ThreadPool();
private final CallbackHelper<Callback<Result>> mCallbackHelper = new CallbackHelper<>();
private final Handler mHandler = new Handler(Looper.getMainLooper());
//AsyncTaskLoader等を使用した場合はこのメソッドを直接呼び出す。
public Result blockingSend(Message message) throws IOException {
ThreadAssertion.assertNotMainThread(); //メインスレッドから呼ばれると例外発生
//ネットワークアクセスなどblockingする処理を行いResultを返す
}
public int send(CallbackLifecycle lifecycle, final Message message, Callback<Result> callback) {
final WeakReference<CallbackLifecycle> ref = new WeakReference<>(lifecycle);
final int seq = mCallbackHelper.getAndIncrementSeq();
mCallbackHelper.put(lifecycle, callback, seq);
//メインスレッド以外でblockingメソッドを実行
mThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
Result result = blockingSend(message);
performDone(ref, seq, result);
} catch (IOException exp) {
performError(ref, seq, exp);
}
}
});
return seq;
}
private void performDone(final WeakReference<CallbackLifecycle> ref, final int seq, final Result result) {
if (ref.get() == null)
return;
mHandler.post(new Runnable() {
@Override
public void run() {
Callback<Result> callback = mCallbackHelper.getAndRemove(ref.get(), seq);
if (callback != null)
callback.done(result);
}
});
}
private void performError(final WeakReference<CallbackLifecycle> ref, final int seq, final Exception exp) {
if (ref.get() == null)
return;
mHandler.post(new Runnable() {
@Override
public void run() {
Callback<?> callback = mCallbackHelper.getAndRemove(ref.get(), seq);
if (callback != null)
callback.error(exp);
}
});
}
public void removeCallbackFor(CallbackLifecycle lifecycle) {
mCallbackHelper.remove(lifecycle);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment