編輯:關於Android編程
AsyncTask是什麼?異步任務,在android中主線程不能做耗時的操作,否則很容易出現ANR異常,所以像訪問網絡,讀取數據庫等一些耗時的操作都放在子線程中,但是子線程是無法更新UI的,我們還需要把得到的結果發送到主線程中做更新UI的處理。這時我們就需要用到Handler或者AsnycTask,其實AsyncTask是對Handler和Thread做了封裝,更加方便調用。
public abstract class AsyncTask普通方法//三個泛型分別表示: 啟動任務執行的輸入參數 , 後台任務執行的進度 , 後台任務執行結果
(1). execute(Params... params) // 調用該方法來啟動執行異步方法 (2). onPreExecute() ; // 在execute(Params... params)方法調用之後立即執行的方法,該方法在主線程中執行, (3). doInBackground(Params... params); // 在onPreExecute()執行之後執行的方法,該方法在子線程中執行,可以用來做一些耗時的操作;在該方法中可以調用publishProgress(Progress... vallues)來更新進度等, (4). onProgressUpdate(Progress... values); // 在調用publishProgress(Progress... values),該方法在UI線程中執行,用來更新進度 (5). onPostExecute(Result result); // 後台執行結束時,該方法調用,在UI線程中執行。後台計算結果被作為參數傳遞給該方法。 (6). onCancelled(); // 當任務取消時調用該方法使用時注意事項:
public class MainActivity extends Activity implements View.OnClickListener { private ProgressBar pb ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pb = (ProgressBar) findViewById(R.id.pb); pb.setMax(100); findViewById(R.id.btn1).setOnClickListener(this); } @Override public void onClick(View v) { asyncTask.execute(); // 調用execute()方法啟動異步任務; } private AsyncTaskasyncTask = new AsyncTask () { @Override protected void onPreExecute() { showToast("調用execute()方法執行異步任務,該方法立即在主線程中執行"); } @Override protected String doInBackground(Void... v) { for(int i=0 ;i<=100;i++){ SystemClock.sleep(500); // 模擬耗時操作 publishProgress(i); //調用該方法更新進度 } return "執行完成"; } @Override // 該方法在調用publishProgress()方法調用之後執行,執行在主線程接收publishProgress()傳遞的參數,用來更新UI界面 protected void onProgressUpdate(Integer... values) { pb.setProgress(values[0]); } @Override // 該方法在doInBackground()方法執行結束後執行,接受其傳遞的參數,該方法在主線程中執行 protected void onPostExecute(String s) { showToast(s); } }; /** * 顯示Toast * @param msg */ private void showToast(String msg){ Toast.makeText(this , msg , Toast.LENGTH_SHORT).show(); } }
剛才說過AsyncTask其內部是對線程和Handler的封裝,簡化我們的使用。現在我們自己來實現一個AsyncTask,以便更好的了解其內部實現原理。
AsyncTask在使用過程中常用的那幾個方法執行順序以及是否執行在UI線程中我們已經做了了解,我們知道在調用execute()的時候開啟異步任務,首先調用的就是onPreExecute()方法,然後在子線程中執行doInBackground()方法,在執行過程中調用publishProgress()方法將執行進度發送到主線程中,通過onProgressUpdate()方法來更新UI;在doInBackground()方法執行完畢以後,執行onPostExecute()方法,將執行結果作為參數傳遞給onPostExecute()。這就是AsyncTask執行流程,下面就是我們自己實現的MyAsyncTask
public abstract class MyAsyncTask{ private static InteranlHandler interHandler ; // 內部封裝Handler用來發送消息,在主線程中更新UI private static final int MSG_PROGRESS = 0 ; // 發送更新UI進度類型的類型 private static final int MSG_RESULT = 1 ; // 發送執行結果的消息類型 public MyAsyncTask(){ interHandler = new InteranlHandler(); // 在創建實例時,內部創建Handler對象 } /** * 調用execute方法,觸發異步任務執行 * @param params */ public void execute(final Params... params){ onPreExecute(); // 首先調用onProExecute()方法 new Thread(){ @Override public void run() { Result result = doInBackground(params); // 在子線程中執行doInBackground方法,將獲取的結果通過finish(Result)方法發送到主線程中 finish(result); } }.start(); } /** *通過AsyncTaskResult將數據封裝起來發送到主線程中 */ private void finish(final Result result){ AsyncTaskResult taskResult = new AsyncTaskResult (MyAsyncTask.this , result); Message msg = Message.obtain(); msg.what = MSG_RESULT ; msg.obj = taskResult ; interHandler.sendMessage(msg); } /** * execute方法執行之前立即在mainTread中執行, */ protected void onPreExecute(){ } /** * 在子線程中執行 * @param paramses * @return */ protected abstract Result doInBackground(Params... paramses); /** * 更新UI,在主線程中執行 * @param progress */ protected void onProgressUpdate(Progress... progress){ } /** * 調用該方法,將數據封裝起來,發送到主線程中,觸發onProgressUpdate方法在主線程中執行 * @param progress */ protected void publishProgress(final Progress... progress){ AsyncTaskResult
這樣就完成了我們自己的AsyncTask,使用方式和AsyncTask一樣。
//創建實例,然後調用execute(Params... params)方法觸發異步任務執行, private MyAsyncTaskmyAsyncTask = new MyAsyncTask () { @Override protected void onPreExecute() { showToast("MyAsyncTask 執行onPreExecute方法,在主線程中執行"); } @Override protected String doInBackground(Void... voids) { for(int i=0;i<=100;i++){ SystemClock.sleep(500); publishProgress(i); } return "MyAsycTask後台方法執行完畢"; } @Override protected void onProgressUpdate(Integer... progress) { pb.setProgress(progress[0]); } @Override protected void onPostExecute(String result) { showToast(result); } };
當我們完成了仿AsyncTask之後,我們對AsyncTask內部實現原理也就一目了然了。AsyncTask內部就是對線程池和Handler的封裝,調用execute方法時,內部會調用executeOnExecutor()方法,該方法執行後,會先調用onPreExecute()方法;然後執行FutureTask任務,這個過程中doInBackground(Params… params)會被調用,如果我們在doInBackground方法中調用publishProgress(Progress… values)方法,內部會通過InternalHandler(繼承Handler)實例來發送一條MESSAGE_POST_PROGRESS消息,更新進度,在InternalHandler中處理消息時,會調用onProgressUpdte(Progress… progress)方法,doInBackground()方法執行完畢後,會發送一條MESSAGE_POST_RESULT消息處理結果,InternalHandler在處理結果時,會調用onPostExecute()方法。
微信裡面有個“附近的人”,相信大家都知道,大概的原理就是調用騰訊地圖的sdk進行定位,然後把個人的定位信息發到微信服務器上進行處理,再把一定范圍內
下面是開始Android編程的好方法:找一些與你想做事情類似的代碼調整它,嘗試讓它做你像做的事情經歷問題使用StackOverflow解決問題對每個你像添加的特征重復上述
接上篇Android 開發第五彈:簡易時鐘(鬧鐘) ,這次是一個時鐘類應用,目前依舊是主要的功能,長得還是很挫。當然了,核心功能是有的……時鐘
前言很多程序猿(媛)都對消息處理機制做過分析,大家都基本了解了MessageQueue、Handler、Looper之間相互之間怎麼協同工作,但是具體到消息是如何傳遞,取