/* * Copyright (c) 2014-2015 Sean Liu. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.baoti.pioneer.app.task; import android.annotation.TargetApi; import android.os.Build; import com.github.baoti.pioneer.BusProvider; import com.github.baoti.pioneer.app.task.compat.AsyncTask; import com.squareup.otto.Bus; import timber.log.Timber; /** * 自动注册到 APP_BUS 的 AsyncTask , 可用于处理后台任务, 并且将后台任务发出的事件 通过 publishProgress 通知 UI. * * Created by liuyedong on 14-12-19. */ public abstract class SafeAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Tasks.ResultOrException<Result>> implements Tasks.SafeTask<Result> { private final boolean subscribe; private Tasks.LifecycleListener lifecycleListener; /** * 用于订阅通知 */ protected final Bus appBus; /** * 是否执行了 onStopped 回调 */ private boolean stopped; /** * 是否正在运行 */ private boolean running; /** * 缓存运行结果 */ private Tasks.ResultOrException<Result> resultOrException; public SafeAsyncTask() { this(false); } public SafeAsyncTask(boolean subscribe) { this.subscribe = subscribe; appBus = BusProvider.APP_BUS; } public <Task extends SafeAsyncTask> Task setLifecycleListener( Tasks.LifecycleListener lifecycleListener) { this.lifecycleListener = lifecycleListener; //noinspection unchecked return (Task) this; } @SafeVarargs public final void executeOnDefaultThreadPool(Params... params) { Tasks.executeOnDefaultThreadPool(this, params); } @Override public boolean isRunning() { return running; } @Override public boolean hasResultOrException() { return resultOrException != null; } @Override public Exception getException() { return resultOrException != null ? resultOrException.exception : null; } @Override public Result getResult() { return resultOrException != null ? resultOrException.result : null; } protected void onStart() { } @SuppressWarnings("unchecked") protected abstract Result doTask(Params... params) throws Exception; protected void onCancel() { } @SuppressWarnings("UnusedParameters") protected void onException(Exception exception) { } @SuppressWarnings("UnusedParameters") protected void onSuccess(Result result) { } @SuppressWarnings("unchecked") @Override protected final Tasks.ResultOrException doInBackground(Params... params) { try { if (subscribe) { appBus.register(this); } try { Timber.v("doTask [%s]", this); Result result = doTask(params); return new Tasks.ResultOrException(result, null); } finally { if (subscribe) { appBus.unregister(this); } } } catch (Exception e) { return new Tasks.ResultOrException(null, e); } } @Override protected final void onPreExecute() { super.onPreExecute(); Timber.v("onStart [%s]", this); running = true; if (lifecycleListener != null) { lifecycleListener.onStarted(this); } onStart(); } private void onStopped() { stopped = true; running = false; if (lifecycleListener != null) { lifecycleListener.onStopped(this); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override protected final void onCancelled(Tasks.ResultOrException<Result> e) { super.onCancelled(e); } @Override protected final void onCancelled() { super.onCancelled(); if (stopped) { return; } Timber.v("onCancel [%s]", this); resultOrException = null; onStopped(); onCancel(); } @Override protected final void onPostExecute(Tasks.ResultOrException<Result> e) { super.onPostExecute(e); if (stopped) { return; } if (isCancelled()) { onCancelled(); return; } resultOrException = e; onStopped(); if (e.exception != null) { Timber.v("onException [%s] - [%s]", this, e.exception); onException(e.exception); } else { Timber.v("onSuccess [%s] - [%s]", this, e.result); onSuccess(e.result); } } }