編輯:關於Android編程
使用的優點:
l 簡單,快捷
l 過程可控
使用的缺點:
l 在使用多個異步操作和並需要進行Ui變更時,就變得復雜起來。
AsyncTask定義了三種泛型類型 Params,Progress和Result。(也是可以指定為空的,如AsyncTask
一個異步加載數據最少要重寫以下這兩個方法:
當然了,還可以重寫以下這三個方法,但不是必須的:
使用AsyncTask類,以下是幾條必須遵守的准則:
1、Task的實例必須在UI thread中創建;
2、execute方法必須在UI thread中調用;
3、不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
4、該task只能被執行一次,多次調用時將會出現異常;
執行的順序是:onPreExecute(),doInBackground(),onProgressUpdate(),onPostExecute()。onCancelled()不一定會執行。
除了doInBackground是在子線程執行,其他的都是在UI線程執行的。
下面說下我們具體是怎麼使用的:
第一步,創建一個異步任務的實例,並且執行,這裡傳入的參數對應的是AsyncTask的第一個參數:
MyTask mTask = new MyTask(); mTask.execute(url);第二步,建立一個異步任務的類,如下:
private class MyTask extends AsyncTask第三步,不是必須的,如果需要取消任務,可以調用:{ //onPreExecute方法用於在執行後台任務前做一些UI操作 @Override protected void onPreExecute() { textView.setText("start loading..."); } //doInBackground方法內部執行後台任務,不可在此方法內修改UI。這裡傳入的參數對應AsyncTask的第一個參數,即execute()函數傳遞過來的 @Override protected String doInBackground(String... params) { ... //做一些耗時的動作 publishProgress(progresses); //progresses對應AsyncTask的第二個參數,同時也是要傳給onProgressUpdate()的參數 ... return result; //返回值對應AsyncTask的第三個參數,同時也是要傳給onPostExecute()的參數 } //onProgressUpdate方法用於更新進度信息 @Override protected void onProgressUpdate(Integer... progresses) { textView.setText("loading..." + progresses[0] + "%"); } //onPostExecute方法用於在執行完後台任務後更新UI,顯示結果 @Override protected void onPostExecute(String result) { textView.setText(result); } //onCancelled方法用於在取消執行中的任務時更改UI @Override protected void onCancelled() { textView.setText("cancelled"); } }
mTask.cancle(true);該函數一旦被調用就不會執行到onPostExecute()了,而是執行onCancelled()方法。
public AsyncTask() { mWorker = new WorkerRunnable就是建立了WorkerRunnable和FutureTask兩個實例,並把mWorker傳遞給了mFuture。() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return postResult(doInBackground(mParams)); } }; mFuture = new FutureTask (mWorker) { @Override protected void done() { ... } }; }
public final AsyncTask調用了executeOnExecutor,繼續看下實現:execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
public final AsyncTask在這裡我們看到了onPreExecute(),因此可以看出onPreExecute()是首先被執行的,然後調用了exec.execute(),從上面的代碼中我們看到exec就是sDefaultExecutor,那麼sDefaultExecutor是什麼東東呢?我們看到了如下代碼:executeOnExecutor(Executor exec, Params... params) { ... mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); …… private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;也就是我們實際調用的是SerialExecutor的execute()方法,看下實現:
private static class SerialExecutor implements Executor { final ArrayDeque首先把任務放到mTasks這個集合裡面;然後判斷mActivie如果為空,就調用scheduleNext ()方法。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); } } }
void innerRun() { if (!compareAndSetState(READY, RUNNING)) return; runner = Thread.currentThread(); if (getState() == RUNNING) { // recheck after setting thread V result; try { result = callable.call(); } catch (Throwable ex) { setException(ex); return; } set(result); } else { releaseShared(0); // cancel } }我們看到有調用callable.call(),而callable就是mWorker了,所以這裡就執行到了下面的函數:
public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return postResult(doInBackground(mParams)); }postResult(doInBackground(mParams))這一句就走到了doInBackground()方法了,並且將它的返回值傳給了postResult,那我們看下postResult的具體實現吧!
private Result postResult(Result result) { Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult原來是使用了sHandler來發送消息,那我們再看下處理消息的地方:(this, result)); message.sendToTarget(); return result; }
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: result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }收到MESSAGE_POST_RESULT就執行finish(),收到MESSAGE_POST_PROGRESS就執行onProgressUpdate()。我們看下finish()的實現:
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }這裡做了一個判斷,根據任務是否被取消來調用不同的方法。
protected final void publishProgress(Progress... values) { if (!isCancelled()) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult至此AsyncTask相關的流程就講的差不多了,可以看到AsyncTask的任務執行是單線程的,關於AsyncTask的任務執行是單線程實現還是多線程實現是經歷了一番變化的,較早的版本是單線程實現,從Android2.X開始,Google把它改為多線程實現,後來發現,多線程實現的話,會有很多需要保證線程安全的額外工作留給開發者,所以從Android3.0開始,又把默認實現改為單線程了。
目錄:1.Fragment概述2.Fragment的生命周期3.Fragment靜態添加使用4.Fragment的動態添加使用5.Fragment之間的通信6.Fragm
本人新手,由於要做郵件發送驗證碼,所以找到和搜集到這些,本人親測完全可以用這是163郵箱的 因為不是企業郵箱填寫的賬號是163的賬號,但是密碼是授
當App中涉及到布局需要展示大量圖片時,你就應該考慮到“圖片比例適配“的問題。當圖片的寬高規格不同時,你設置展示的ImageView一. 自定義
最近在網上看到時間軸的布局效果,嘗試按照這個原理,實現物流跟蹤的效果,目前已經實現了,效果如下圖。 界面布局主要是通過listView來