編輯:關於Android編程
1. Params
這三個參數的用途如下:
1. Params
在執行AsyncTask時需要傳入的參數,可用於在後台任務中使用。
2. Progress
後台任務執行時,如果需要在界面上顯示當前的進度,則使用這裡指定的泛型作為進度單位。
3. Result
當任務執行完畢後,如果需要對結果進行返回,則使用這裡指定的泛型作為返回值類型。
Android SDK中給出的一個AsyncTask用法如下:
private class DownloadFilesTask extends AsyncTask(URL, Integer, Long) {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
new DownloadFilesTask().execute(url1, url2, url3);AsyncTask的源碼
當初使用AsyncTask的時候,一直不明白onProcessUpdate為何會定期被調用。後來在工作中要實現一個定時更新任務進度的功能,我們用的是一個Handler給自己發送消息來進行定時刷新。現在研究了一下AsyncTask的實現原理,發現它也是使用Handler給自己發送消息的原理來實現定時刷新。當我選用的是Android 4.4的源碼,若大家能搞懂AsyncTask的實現原理,也能自己寫一個簡單的AsyncTask。
首先看看構造函數:注意,構造函數一定要在UI中調用。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground
()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
} 這個函數初試化了兩個變量:mWorker和mFuture。mWorker是一個Callable對象,mFuture是一個實現了Runnable和Future的對象。啟動AsyncTask調用的是execute(Params)public final AsyncTask該方法調用了executeOnExecutor()方法,代碼如下:execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
public final AsyncTask該方法先設置運行狀態,然後調用onPreExecute,最後調用exec.execute(mFuture).傳入的exec是sDefaultExecutor, sDefaultExecutor是一個SerialExecutor對象,源代碼如下:executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
當調用sDefaultExecutor.execute(runnable),該方法用一個ArrayDeque來保存runnable,runnable會在合適的時候被調用。第一次運行mActivity等於null了,於是會調用scheduleNext()方法。在這個方法中會從隊列的頭部取值,並賦值給mActive對象,然後調用THREAD_POOL_EXECUTOR去執行取出的取出的Runnable對象。這裡使用了一個try finally代碼塊,並在finally中調用了scheduleNext()方法,每次當一個任務執行完畢後,下一個任務才會得到執行,SerialExecutor模仿的是單一線程池的效果,如果我們快速地啟動了很多任務,同一時刻只會有一個線程正在執行,其余的均處於等待狀態。
sDefaultExecutor.execute(Runnable)傳入的對象是mFuture,mFuture是一個FutureTask對象,其構造函數如下所示:
public FutureTask(Callable由AsyncTask的構造函數可知,FutureTask中的callable是mWorkder對象。FutureTask的run()代碼如下所示:callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
} 因此,最終會調用mWorker的call()。mWorker的call()位於AsyncTask的構造函數中,大家可以發現其先調用doInBackgroud(Params),然後調用postResult().postResult(Result)的源代碼如下:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
} sHandler是一個InternalHandler,代碼如下:
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
當傳入的是一條MESSAGE_POST_RESULT消息,就會去執行AsyncTask.finish()方法,如果這是一條MESSAGE_POST_PROGRESS消息,就會去執行onProgressUpdate()方法。當我們在doInBackgroud(Params)中利用for循環來調用publishProgress(Progress... values),就會模擬出 protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult
它首先會判斷線程是否已經結束,若沒結束,則sHandler給自己發送一個消息,消息的類型為MESSAGE_POST_PROGRESS,sHandler.handleMessage(Message)則會調用onProgressUpdate(Progress... values)。 private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}postResult(Result)已經在前面有過講解,在此不再贅述。
Android二維碼ZXING3.0(201403發布)接入
ZXING開源項目官方網站https://github.com/zxing/zxing/tree/zxing-3.0.0。 架包下載地址http://repo1.mave
Android 幾種屏幕間跳轉的跳轉Intent Bundle
屏幕使用一個活動來實現,屏幕間是相互獨立的,屏幕之間的跳轉關系通過Intent來實現。屏幕間跳轉分為以下幾類:1. 屏幕1直接跳轉到屏幕2 &nbs
詳解Android原生json和fastjson的簡單使用
android原生操作json數據主要是兩個類 JSONObject 操作對象 JONSArray操作json數組對象轉j
新版手機QQ怎麼綁定和解除銀行卡 手機QQ綁定銀行卡辦法 手機QQ怎
新版手機QQ有一個洗功能就是QQ錢包,可以發紅包,如果我們想要使用qq錢包的功能的話,一般很多時候都要求我們綁定銀行卡的。那麼新版手機QQ怎麼綁定和解除銀行