package com.xiaomi.xms.sales.loader;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.os.AsyncTask;
import android.os.Handler.Callback;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import com.xiaomi.xms.sales.activity.BaseActivity;
import com.xiaomi.xms.sales.cache.DbCache;
import com.xiaomi.xms.sales.cache.DbCache.DbCacheItem;
import com.xiaomi.xms.sales.db.DBContract;
import com.xiaomi.xms.sales.db.DBContract.Cache;
import com.xiaomi.xms.sales.loader.BaseResult.ResultStatus;
import com.xiaomi.xms.sales.model.Tags;
import com.xiaomi.xms.sales.request.Request;
import com.xiaomi.xms.sales.util.LogUtil;
import com.xiaomi.xms.sales.util.ThreadPool;
import com.xiaomi.xms.sales.xmsf.account.LoginManager;
public abstract class BaseLoader<GenericResult extends BaseResult> extends Loader<GenericResult> {
private static final String TAG = "BaseLoader";
// Loader 加载结果
protected GenericResult mResult;
// 是否正在加载,如果正在加载则取消加载请求
protected volatile boolean mIsLoading;
// 是否需要读取数据库中的缓存数据
protected boolean mNeedDatabase;
// 是否需要从远程获取数据
protected boolean mNeedServer;
// 是否需要将结果传递给界面进行处理
protected boolean mNeedDeliverResult;
// 结果是否已经发送给过界面
private boolean mHasDeliverdResult;
// 任务队列,当界面是分布加载的时候,只需要按照顺序初始化Task即可
protected List<AsyncTask<Void, Void, GenericResult>> mTaskList;
private int mNextExecuteTask;
// 加载任务时候是否有进度通知
private ProgressNotifiable mProgressNotifiable;
protected DbCache mCache;
protected String mEtag;
private WeakReference<BaseActivity> mBaseActivityRef;
public BaseLoader(Context context) {
super(context);
if (context instanceof BaseActivity) {
mBaseActivityRef = new WeakReference<BaseActivity>((BaseActivity) context);
}
mIsLoading = false;
mNeedDatabase = true;
mNeedServer = true;
mNeedDeliverResult = true;
mHasDeliverdResult = false;
mTaskList = new ArrayList<AsyncTask<Void, Void, GenericResult>>();
mNextExecuteTask = 0;
mCache = new DbCache(context);
mResult = getResultInstance();
}
/**
* 重新加载数据
*/
public void reload() {
if (!this.isLoading()) {
this.mNeedDatabase = false;
this.forceLoad();
}
}
public void setNeedDatabase(boolean needDatabase) {
this.mNeedDatabase = needDatabase;
}
public void setNeedServer(boolean needServer) {
this.mNeedServer = needServer;
}
public boolean isLoading() {
return mIsLoading;
}
public void setProgressNotifiable(ProgressNotifiable progressNotifiable) {
this.mProgressNotifiable = progressNotifiable;
// 注册监听器时直接告知当前状态
if (progressNotifiable != null) {
progressNotifiable.init(dataExists(), mIsLoading);
}
}
@SuppressWarnings("unchecked")
@Override
protected void onStartLoading() {
if (mResult.getCount() > 0) {
// 这里浅克隆结果,避免由于结果完全一致,不会刷新界面
deliverResult((GenericResult) mResult.shallowClone());
}
if (!mIsLoading && (mResult.getCount() == 0 || takeContentChanged())) {
forceLoad();
}
}
@Override
protected void onForceLoad() {
mTaskList.clear();
mNextExecuteTask = 0;
initTaskList(mTaskList);
executeNextTask();
}
/**
* 子类可以继承该方法自定义任务列表,此时默认列表不起作用(一个数据库任务和一个网络任务)
*/
protected void initTaskList(List<AsyncTask<Void, Void, GenericResult>> tasks) {
if (mNeedDatabase) {
DatabaseTask task = getDatabaseTask();
if (task != null) {
tasks.add(task);
}
}
if (mNeedServer) {
UpdateTask task = getUpdateTask();
if (task != null) {
tasks.add(task);
}
}
}
/**
* 调用该方法将会执行下一个任务
*/
protected void executeNextTask() {
if (hasNextTask()) {
AsyncTask<Void, Void, GenericResult> task = null;
while (task == null && hasNextTask()) {
task = mTaskList.get(mNextExecuteTask);
mNextExecuteTask++;
}
if (task != null) {
task.execute();
}
}
}
protected boolean hasNextTask() {
return mNextExecuteTask < mTaskList.size();
}
protected DatabaseTask getDatabaseTask() {
return new DatabaseTask();
}
protected UpdateTask getUpdateTask() {
return null;
}
protected boolean dataExists() {
// 数据存在并且已经发送给界面过
return mResult.getCount() > 0 && mHasDeliverdResult;
}
protected abstract GenericResult parseResult(JSONObject json, GenericResult baseResult)
throws Exception;
protected abstract GenericResult getResultInstance();
/**
* 子类的任务都需要继承该类以获得任务管理和进度通知特性
*/
protected abstract class BaseTask extends AsyncTask<Void, Void, GenericResult> {
@Override
protected void onPreExecute() {
/*ConnectivityManager connectivityManager = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
HttpClient httpclient = new DefaultHttpClient();
HttpParams params = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(params , 1);
HttpConnectionParams.setSoTimeout(params ,1); */
// // 设置网络超时时间(请求和响应)
// NetWorkConnection.getHttpClient().getParams()
// .setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
// 35000);
// NetWorkConnection.getHttpClient().getParams()
// .setParameter(CoreConnectionPNames.SO_TIMEOUT, 35000);
mIsLoading = true;
if (mProgressNotifiable != null) {
mProgressNotifiable.startLoading(dataExists());
}
}
@Override
protected void onPostExecute(GenericResult result) {
mIsLoading = false;
final ResultStatus status = result.getResultStatus();
// 如果出错
if (status != ResultStatus.OK) {
if (mProgressNotifiable != null) {
mProgressNotifiable.onError(dataExists(), status,
new Callback() {
@Override
public boolean handleMessage(Message message) {
if (status == BaseResult.ResultStatus.NETWROK_ERROR) {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
} else if (status == BaseResult.ResultStatus.AUTH_ERROR) {
if (mBaseActivityRef != null) {
BaseActivity ba = mBaseActivityRef.get();
if (ba != null) {
LoginManager.getInstance().setSystemLogin(false);
ba.gotoLogin();
}
}
} else {
reload();
}
return true;
}
});
}
} else {
mResult = result;
if (mNeedDeliverResult) {
deliverResult(result);
mHasDeliverdResult = true;
} else {
mNeedDeliverResult = true;
}
// 如果数据正常,那么停止停止加载进度,显示结果
if (mProgressNotifiable != null && !hasNextTask()) {
mProgressNotifiable.stopLoading(dataExists());
}
}
executeNextTask();
}
protected GenericResult parseTaskResult(JSONObject json) {
GenericResult result = getResultInstance();
if (result == null) {
throw new IllegalStateException(
"The parsed result should not be null, you must construct" +
"a result to indicate the task state");
}
try {
if(json.has(Tags.HEADER)){
if(json.optJSONObject(Tags.HEADER).has(Tags.CODE)){
if(json.optJSONObject(Tags.HEADER).optInt(Tags.CODE) == 205){
result.setResultStatus(ResultStatus.IP_ERROR);
return result;
}
}
}
result = parseResult(json, result);
} catch (Exception e) {
result.setResultStatus(ResultStatus.DATA_ERROR);
e.printStackTrace();
}
return result;
}
}
/**
* 获取缓存的key
*/
protected abstract String getCacheKey();
/**
* 缓存信息是否与用户相关,如果相关,那么在切换帐号的时候需要清除缓存
*/
protected boolean isUserRelated() {
return false;
}
public void saveCacheToDB(String key, String content, String etag) {
if (TextUtils.isEmpty(content)) {
return;
}
ContentValues values = new ContentValues();
String cacheKey = getCacheKey();
values.put(Cache.KEY, cacheKey);
values.put(Cache.CONTENT, content);
values.put(Cache.ETAG, etag);
if (isUserRelated() && LoginManager.getInstance().hasLogin()) {
values.put(Cache.ACCOUNT_ID, LoginManager.getInstance().getUserId());
}
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(Cache.CONTENT_URI);
builder.withSelection(Cache.KEY + "=?", new String[] {
key
});
operations.add(builder.build());
builder = ContentProviderOperation.newInsert(Cache.CONTENT_URI);
builder.withValues(values);
operations.add(builder.build());
try {
getContext().getContentResolver().applyBatch(DBContract.AUTHORITY, operations);
} catch (RemoteException e) {
LogUtil.e(TAG, "saveCategoryToDB: failed");
e.printStackTrace();
} catch (OperationApplicationException e) {
LogUtil.e(TAG, "saveCategoryToDB: failed");
e.printStackTrace();
}
}
/**
* 从数据库将数据载入缓存
*/
protected class DatabaseTask extends BaseTask {
@Override
protected GenericResult doInBackground(Void... params) {
GenericResult result = getResultInstance();
DbCacheItem item = mCache.getItem(getCacheKey());
if (item != null && item.mEtag != null) {
mEtag = item.mEtag;
}
if (item != null) {
try {
JSONObject json = new JSONObject(item.mContent);
GenericResult newResult = parseTaskResult(json);
result = onDataLoaded(mResult, newResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 子类可以对获取的数据进行处理,如果该方法返回null,则数据和界面不会更新
*/
protected GenericResult onDataLoaded(GenericResult oldResult, GenericResult newResult) {
return newResult;
}
}
/**
* 从服务器将数据载入缓存和数据库
*/
protected abstract class UpdateTask extends BaseTask {
private boolean needSaveToDb;
public UpdateTask() {
super();
this.needSaveToDb = true;
}
public UpdateTask(boolean needSaveToDb) {
super();
this.needSaveToDb = needSaveToDb;
}
/**
* @return the update task result. Null to indicate our service error.
*/
@Override
protected GenericResult doInBackground(Void... params) {
Request request = getRequest();
if (mEtag != null) {
request.addHeader("If-None-Match", mEtag);
}
int status = request.getStatus();
GenericResult result = getResultInstance();
if (status == Request.STATUS_OK) {
final String etag = request.getEtag();
JSONObject mainObject = request.requestJSON();
GenericResult newResult = parseTaskResult(mainObject);
result = onDataLoaded(mResult, newResult);
final String jonsString = mainObject.toString();
if (needSaveToDb && mNeedDatabase && !TextUtils.isEmpty(getCacheKey())) {
ThreadPool.execute(new Runnable() {
@Override
public void run() {
saveCacheToDB(getCacheKey(), jonsString, etag);
}
});
}
return result;
} else if (status == Request.STATUS_NOT_MODIFIED) {
LogUtil.d(TAG, "url: " + request.getRequestUrl() + " is NOT MODIFIED");
mNeedDeliverResult = false;
result = mResult;
} else if (status == Request.STATUS_NETWORK_UNAVAILABLE) {
result.setResultStatus(ResultStatus.NETWROK_ERROR);
} else if (status == Request.STATUS_AUTH_ERROR) {
result.setResultStatus(ResultStatus.AUTH_ERROR);
} else {
result.setResultStatus(ResultStatus.SERVICE_ERROR);
}
return result;
}
/**
* 获得请求网络数据的Request
*/
protected abstract Request getRequest();
/**
* 子类可以对获取的数据进行处理,如果该方法返回null,则数据和界面不会更新
*/
protected GenericResult onDataLoaded(GenericResult oldResult, GenericResult newResult) {
return newResult;
}
}
}