編輯:Android編程入門
---恢復內容開始---
因為android的UI線程是不安全的,如果你UI線程裡執行一些耗時任務,很容易就導致程序崩潰。並且目前網絡任務也不能夠在UI線程裡執行。處理這些問題除了直接寫一個線程以外,Android還提供一個AsyncTask(異步任務類)來更簡單的處理一些耗時任務。
AsyncTask<>是一個抽象類,通常用於繼承,繼承時需要指定三個泛型參數。
1、Params:啟動任務時傳入的參數的類型。這是一個數組,可以傳多個參數。調用時使用params[0]、params[1]、params[2]來獲取。
2、Progress:後台任務完成的進度值的類型。
3、Result:後台任務執行完畢返回結果的類型。
使用AsyncTask需要如下三步:
1、繼承抽象類,實現一個子類,傳入三個泛型參數。如果有參數不需要使用可設為Void。
2、根據需要,可實現以下方法。
3、最後用新建我們繼承類後的結果,然後調用execute(Params... params)。
注意:對象必須在UI線程中創建、execute方法必須在UI線程中調用、以上四個方法都需系統自動調用、每個對象只能被執行一次,多次調用引發異常。
講了那麼多鋪墊,讓我們來講個例子吧~
我現在想從互聯網上下載一張圖片,就使用這個AsyncTask來做一下吧~
為讓所有方法都實現一次,我們用兩種方法實現:1、下載完畢後直接進行顯示。2、一邊加載一邊顯示進度,加載完畢顯示圖片。
下面是第一種的代碼,相對簡單一點,只用了兩個函數。
public class MainActivity extends Activity { int downloadSize; int fileSize; Button bn; ImageView iv; ProgressBar progressBar; String url = "/hvtimg/bjafjc/3xglb9xf.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down); iv = (ImageView) findViewById(R.id.image); MyOnClickListener myOnClickListener = new MyOnClickListener(); bn.setOnClickListener(myOnClickListener); } class MyOnClickListener implements android.view.View.OnClickListener{ @Override public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload(); asyncDownload.execute(url); } } class AsyncDownload extends AsyncTask<String, Integer, Bitmap> { @Override protected Bitmap doInBackground(String... params) { String imageUrl = params[0]; URL url; try { url = new URL(imageUrl); InputStream is = url.openStream(); BitmapFactory.Options op = new BitmapFactory.Options(); op.inSampleSize = 2; Bitmap bitmap = BitmapFactory.decodeStream(is, null, op); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); iv.setImageBitmap(result); } } }
上面的代碼的功能是點擊按鈕,然後doInBackground後台下載圖片,下載完畢onPostExecute顯示圖片。僅僅使用了兩個函數,但是實現了AsyncTask的核心功能。
然後讓我們感受一下能夠顯示進度的。
public class MainActivity extends Activity { int downloadSize; int fileSize; Button bn; ImageView iv; ProgressBar progressBar; String url = "/hvtimg/bjafjc/3xglb9xf.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down); iv = (ImageView) findViewById(R.id.image); progressBar = (ProgressBar) findViewById(R.id.bar); MyOnClickListener myOnClickListener = new MyOnClickListener(); bn.setOnClickListener(myOnClickListener); } Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { } }; class MyOnClickListener implements android.view.View.OnClickListener{ @Override public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload(); asyncDownload.execute(url); } } class AsyncDownload extends AsyncTask<String, Integer, Void> { @Override protected Void doInBackground(String... params) { String imageUrl = params[0]; try { URL url = new URL(imageUrl); URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); fileSize = conn.getContentLength(); publishProgress(0x111); FileOutputStream fos = new FileOutputStream(getPath()); byte[] bytes = new byte[1024]; int len = -1; while((len = is.read(bytes))!=-1) { fos.write(bytes, 0, len); downloadSize+=len; publishProgress(0x222); } publishProgress(0x333); is.close(); fos.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); switch(values[0]) { case 0x111: progressBar.setMax(fileSize); break; case 0x222: progressBar.setProgress(downloadSize); break; case 0x333: try { if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ FileInputStream fis = new FileInputStream(getPath()); iv.setImageBitmap(BitmapFactory.decodeStream(fis)); } downloadSize = 0; fileSize = 0; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } break; } } } public String getPath() { File root = getExternalCacheDir(); if (root != null) { return root.getAbsolutePath() + "test.jpg"; } return null; } }
這裡實現的功能是點擊下載按鈕,後台從互聯網加載文件,首先獲取文件大小,設置progressbar最大值,然後一邊下載、一邊存入本地、一邊設置progressbar的值,實現進度條。下載完畢從本地獲取圖片顯示出來。這一次多使用了顯示進度的函數onProgressUpdate。
其實,onProgressUpdate這個函數一般我們在線程裡會用Handler來實現。
在AsyncTask給我們把平常使用線程進行異步操作的所用東西打包在一起了,不得不說確實省了一些事。
實際上能夠用AsyncTask實現的東西完全可以直接用線程來實現~
我在些第二個代碼的時候寫順了手,用Handler實現了一遍,大家在下面可以看一下。
public class MainActivity extends Activity { int downloadSize; int fileSize; Button bn; ImageView iv; ProgressBar progressBar; String url = "/hvtimg/bjafjc/3xglb9xf.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down); iv = (ImageView) findViewById(R.id.image); progressBar = (ProgressBar) findViewById(R.id.bar); MyOnClickListener myOnClickListener = new MyOnClickListener(); bn.setOnClickListener(myOnClickListener); } Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch(msg.what) { case 0x111: progressBar.setMax(fileSize); break; case 0x222: progressBar.setProgress(downloadSize); break; case 0x333: try { if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ FileInputStream fis = new FileInputStream(getPath()); iv.setImageBitmap(BitmapFactory.decodeStream(fis)); } downloadSize = 0; fileSize = 0; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } break; } } }; class MyOnClickListener implements android.view.View.OnClickListener{ @Override public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload(); asyncDownload.execute(url); } } class AsyncDownload extends AsyncTask<String, Integer, Void> { @Override protected Void doInBackground(String... params) { String imageUrl = params[0]; try { URL url = new URL(imageUrl); URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); fileSize = conn.getContentLength(); handler.sendEmptyMessage(0x111); FileOutputStream fos = new FileOutputStream(getPath()); byte[] bytes = new byte[1024]; int len = -1; while((len = is.read(bytes))!=-1) { fos.write(bytes, 0, len); downloadSize+=len; handler.sendEmptyMessage(0x222); } handler.sendEmptyMessage(0x333); is.close(); fos.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } } public String getPath() { File root = getExternalCacheDir(); if (root != null) { return root.getAbsolutePath() + "test.jpg"; } return null; } }
啦啦啦,就到這裡吧~
今天把公司閒置的一台Mac-mini重裝了下系統感覺用著速度還不錯,平時上班用的機器USB有些問題,所以打算用這台Mac。以往開發用Intellij Idea就夠用,但是
導讀增強的Doze模式後台優化Data Saver 一.增強的Doze模式Android N對Android M引進的Doze模式進行了進一步的增強,變化體現在
Android Fragment的生命周期和Activity類似,實際可能會涉及到數據傳遞,onSaveInstanceState
一直關注App的熱修復的技術發展,之前做的應用也沒用使用到什麼熱修復開源框架。在App的熱修復框架沒有流行之前,做的應用上線後發現一個小小的Bug,就要馬上發一個新的版本