package com.netease.nim.demo.common.infra;
import android.os.Handler;
public abstract class Task {
private static final String ENCLOSURE = "<>";
private static final int RETRY_COUNT = 1;
/*package*/ static class Info {
/** background */
boolean background;
/** key */
String key;
/** parameters */
Object[] params;
Info(boolean background, String key, Object[] params) {
this.background = background;
this.key = key;
this.params = params;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("B");
sb.append(ENCLOSURE.charAt(0));
sb.append(background ? "T" : "F");
sb.append(ENCLOSURE.charAt(1));
sb.append(" ");
sb.append("K");
sb.append(ENCLOSURE.charAt(0));
sb.append(key);
sb.append(ENCLOSURE.charAt(1));
return sb.toString();
}
}
/*package*/ static class State {
/** cancelled */
boolean cancelled;
/** chances */
int chances;
/** pending */
boolean pending;
/** fault */
boolean fault;
State() {
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("C");
sb.append(ENCLOSURE.charAt(0));
sb.append(chances);
sb.append(ENCLOSURE.charAt(1));
sb.append(" ");
sb.append("P");
sb.append(ENCLOSURE.charAt(0));
sb.append(pending ? "T" : "F");
sb.append(ENCLOSURE.charAt(1));
return sb.toString();
}
}
/** handler for publish states */
/*package*/ Handler handler;
/** task info */
/*package*/ Info info;
/** task state */
/*package*/ State state;
public void cancel() {
state.cancelled = true;
}
public void setProperty(int prop, Object data) {
// NOP
}
protected boolean background() {
return info.background;
}
protected String key() {
return info.key;
}
protected Object[] params() {
return info.params;
}
protected boolean cancelled() {
return state.cancelled;
}
protected int scheduled() {
return state.chances;
}
protected void pending() {
state.pending = true;
}
protected boolean giveup() {
// give up
boolean giveup = scheduled() > RETRY_COUNT;
// mark pending if proceed
if (!giveup) {
pending();
}
return giveup;
}
/*package*/ boolean schedule() {
// update chances
state.chances++;
// reset pending
state.pending = false;
// execute
Object[] results = null;
try {
results = execute(info.params);
} catch (Throwable tr) {
onException(tr);
// fault
state.fault = true;
}
// no fault and pending
if (!state.fault && state.pending) {
// not proceed
return false;
}
// publish result
publishResult(results);
return true;
}
/**
* execute
*
* @param params
* @return results
*/
protected abstract Object[] execute(Object[] params);
/**
* on exception
* @param tr throwable
*/
protected void onException(Throwable tr) {
// save
// AppCrashHandler.getInstance(null).saveException(tr, false);
};
/**
* on handle result
* @param results
*/
protected void onHandleResult(Object[] results) {};
/**
* on publish result
* @param results
*/
protected void onPublishResult(Object[] results) {}
/**
* on publish progress
* @param params
*/
protected void onPublishProgress(Object[] params) {}
/**
* publish result
* @param results
*/
protected final void publishResult(Object[] results) {
publish(true, results);
}
/**
* publish progress
* @param params
*/
protected final void publishProgress(Object[] params) {
publish(false, params);
}
private final void publish(final boolean result, final Object[] params) {
if (info.background && handler != null) {
// shift to looper thread of handler to publish
handler.post(new Runnable() {
@Override
public void run() {
// publish on current thread
onPublish(result, params);
}
});
} else {
// publish on current thread
onPublish(result, params);
}
}
private final void onPublish(boolean result, Object[] params) {
if (result) {
onHandleResult(params);
onPublishResult(params);
} else {
onPublishProgress(params);
}
}
public final String dump(boolean statefull) {
StringBuilder sb = new StringBuilder();
// info
sb.append(info);
// state
if (statefull) {
sb.append(" ");
sb.append(state);
}
return sb.toString();
}
@Override
public String toString() {
return dump(true);
}
}