com.stanfy.enroscar.async.internal.WrapAsyncLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of enroscar-content Show documentation
Show all versions of enroscar-content Show documentation
Helper classes and extended abstractions for Android loaders, content resolvers, and DB access.
package com.stanfy.enroscar.async.internal;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.Loader;
import com.stanfy.enroscar.async.Async;
import com.stanfy.enroscar.async.AsyncObserver;
/**
* Loader that backs {@link com.stanfy.enroscar.async.Async} result.
* @param data type
*
* @author Roman Mazur - Stanfy (http://stanfy.com)
*/
final class WrapAsyncLoader extends Loader> {
/** Main thread handler. */
private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
private final AsyncContext context;
private Async async;
private Result result;
/** Data observer. */
private final AsyncObserver observer = new AsyncObserver() {
@Override
public void onError(final Throwable e) {
post(new Result(null, e));
}
@Override
public void onResult(final D data) {
post(new Result<>(data, null));
}
};
public WrapAsyncLoader(final AsyncContext context) {
super(context.applicationContext);
this.context = context;
}
@Override
protected void onForceLoad() {
if (async != null) {
async.cancel();
}
async = context.provideAsync();
if (async == null) {
throw new IllegalArgumentException("Async can't be null. Have you implemented @Load or @Send method?");
}
async.subscribe(observer);
}
@Override
protected void onStartLoading() {
if (result != null) {
deliverResult(result);
}
if (takeContentChanged() || async == null) {
forceLoad();
}
}
@Override
public void deliverResult(final Result data) {
if (isReset()) {
onReleaseData(data);
return;
}
Result oldData = result;
result = data;
if (isStarted()) {
super.deliverResult(data);
}
if (oldData != null && data != oldData) {
onReleaseData(oldData);
}
}
@Override
protected void onStopLoading() {
if (async != null) {
async.cancel();
async = null;
}
}
@Override
protected void onReset() {
if (result != null) {
onReleaseData(result);
}
}
private void onReleaseData(final Result result) {
if (result.data != null) {
context.releaseData(result.data);
}
}
private void post(final Result result) {
if (Looper.getMainLooper() == Looper.myLooper()) {
deliverResult(result);
} else {
MAIN_HANDLER.post(new Runnable() {
@Override
public void run() {
deliverResult(result);
}
});
}
}
/** Execution result. */
static final class Result {
final D data;
final Throwable error;
Result(final D data, final Throwable error) {
this.data = data;
this.error = error;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof Result)) {
return false;
}
@SuppressWarnings("unchecked")
Result r = (Result) o;
if (data == null && error == null) {
return r.data == null && r.error == null;
}
return data != null ? data.equals(r.data) : error.equals(r.error);
}
@Override
public int hashCode() {
if (data == null && error == null) {
return 0;
}
return data != null ? data.hashCode() : error.hashCode();
}
}
}