編輯:關於Android編程
為什麼要用異步任務?
在android中只有在主線程才能對ui進行更新操作,而其它線程不能直接對ui進行操作
android本身是一個多線程的操作系統,我們不能把所有的操作都放在主線程中操作 ,比如一些耗時操作。如果放在主線程中 會造成阻塞 而當阻塞事件過長時 系統會拋出anr異常。所以我們要使用異步任務。android為我們提供了一個封裝好的組件asynctask。
AsyncTask可以在子線程中更新ui,封裝簡化了異步操作。適用於簡單的異步處理。如果多個後台任務時就要使用Handler了 在這裡就不再說明。
AsyncTask通常用於被繼承。AsyncTask定義了三種泛型類型
Params:啟動任務時輸入的參數類型
Progress:後台任務執行的百分比
Result:執行任務完成後返回結果的類型
繼承AsyncTask後要重寫的方法有:
doInBackgroud:必須重寫,異步執行後台線程要完成的任務,耗時任務要寫在這裡,並且在這裡不能操作ui。可以調用 publishProgress方法來更新實時的任務進度
onPreExecute:執行耗時操作前調用,可以完成一些初始化操作
onPostExecute:在doInBackground 執行完成後,主線程調用此方法,可以在此方法中操作ui
onProgressUpdate:在doInBackgroud方法中調用publishProgress方法,更新任務的執行進度後 就會調用這個方法
下面通過一個實例來了解AsyncTask
首先附上運行結果
布局文件:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"><button android:id="@+id/btn_download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="點擊下載"> <framelayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <imageview android:id="@+id/iv_image" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaletype="fitCenter"> </imageview></framelayout></button></linearlayout>MainActivity
package com.example.asynctask; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URLConnection; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity implements OnClickListener{ private ImageView image; private ProgressDialog progress; private Button btn_download; private static String URL="http://img4.imgtn.bdimg.com/it/u=1256159061,743487979&fm=21&gp=0.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); image=(ImageView) findViewById(R.id.iv_image); btn_download=(Button) findViewById(R.id.btn_download); progress=new ProgressDialog(this); progress.setIcon(R.drawable.ic_launcher); progress.setTitle("提示信息"); progress.setMessage("正在下載,請稍候..."); progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); btn_download.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub new MyAsyncTask().execute(URL); } /* * String*********對應我們的URL類型 * Integer********進度條的進度值 * BitMap*********異步任務完成後返回的類型 * */ class MyAsyncTask extends AsyncTask{ //執行異步任務(doInBackground)之前執行,並且在ui線程中執行 @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); if(image!=null){ image.setVisibility(View.GONE); } //開始下載 對話框進度條顯示 progress.show(); progress.setProgress(0); } @Override protected Bitmap doInBackground(String... params) { // TODO Auto-generated method stub //params是一個可變長的數組 在這裡我們只傳進來了一個url String url=params[0]; Bitmap bitmap=null; URLConnection connection; InputStream is;//用於獲取數據的輸入流 ByteArrayOutputStream bos;//可以捕獲內存緩沖區的數據,轉換成字節數組。 int len; float count=0,total;//count為圖片已經下載的大小 total為總大小 try { //獲取網絡連接對象 connection=(URLConnection) new java.net.URL(url).openConnection(); //獲取當前頁面的總長度 total=(int)connection.getContentLength(); //獲取輸入流 is=connection.getInputStream(); bos=new ByteArrayOutputStream(); byte []data=new byte[1024]; while((len=is.read(data))!=-1){ count+=len; bos.write(data,0,len); //調用publishProgress公布進度,最後onProgressUpdate方法將被執行 publishProgress((int)(count/total*100)); //為了顯示出進度 人為休眠0.5秒 Thread.sleep(500); } bitmap=BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.toByteArray().length); is.close(); bos.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bitmap; } //在ui線程中執行 可以操作ui @Override protected void onPostExecute(Bitmap bitmap) { // TODO Auto-generated method stub super.onPostExecute(bitmap); //下載完成 對話框進度條隱藏 progress.cancel(); image.setImageBitmap(bitmap); image.setVisibility(View.VISIBLE); } /* * 在doInBackground方法中已經調用publishProgress方法 更新任務的執行進度後 * 調用這個方法 實現進度條的更新 * */ @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); progress.setProgress(values[0]); } } }
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
接上篇Android 開發第五彈:簡易時鐘(鬧鐘) ,這次是一個時鐘類應用,目前依舊是主要的功能,長得還是很挫。當然了,核心功能是有的……時鐘
本文實例講述了Android編程實現監聽EditText變化的方法。分享給大家供大家參考,具體如下:監聽EditText中的內容的變化。在EditText沒有找到一個se
ViewRoot目前這個類已經沒有了,是老版本中的一個類,在Android2.2以後用ViewRootImpl代替ViewRoot,對應於ViewRootImpl.jav
前言在一些APP中我們可以看到一些存放標簽的容器控件,和我們平時使用的一些布局方式有些不同,它們一般都可以自動適應屏幕的寬度進行布局,根據對自定義控件的一些理解,今天寫一