標籤:android listview之asynctask 類比手機小幫手下載
在學習了javaSE過後,現在開始繼續我的android生活,之前學習完JavaSE,通過UI介面做過類比遊戲《貪吃蛇》和基本版計算機,現在學習Android接近有20天的時間,開始製作類比手機小幫手下載,製作手機小幫手下載,關鍵是練習一下listview,和listview一些相關的最佳化,以及最佳化所產生的一些bug和解決。
本次需呀用到hfs外部軟體,來解決網路的問題,650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/73/6D/wKiom1X9VpOycSC0AAEplbbXHiU884.jpg" title="hfs.png" alt="wKiom1X9VpOycSC0AAEplbbXHiU884.jpg" />和一些圖片,用於下載時候的顯示。例如手機qq、、等一些軟體,
下載軟體的時候需要下載是時間,因為我們的main主線程不能做耗時工作,所以下載的時候需要在子線程裡面下載,這邊需要用的AsyncTask。AsyncTask中的doInBackground是在子線程中下載,onProgressUpdate、onPostExecute(String)和onPostExecute都是在主線程中操作,onProgressUpdate是在doInBackground中下載一半的時候,想要對主線程進行操作,onPostExecute是要進行下載之前才執行,onPostExecute(String)是下載之後才操作。
doInBackground(String)在下載的過程中我們需要傳輸下載路徑。
下載用到URL,例如:URL url = new URL(imageUrl);剛開始開啟軟體的時候,一開始顯示整個頁面配置,和剛開始我們軟體的表徵圖,log。都需要下載,下載圖片的用到BitmapFactory,例如:Bitmap bitmap=BitmapFactory.decodeStream(openStream);單下載完成後需要在頁面中更改,,因為主線程中不能做頁面的更改進行一系列的操作,所以需要在doInBackground中將下載好的bitmap return到onPostExecute,在onPostExecute中可以對主線程進行做一系列的操作,image.setImageBitmap(result);這樣,一開始的基本頁面既可以完成,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/73/6F/wKiom1X9aCGSue_kAAcWigzwBUk090.jpg" title="image_02.png" alt="wKiom1X9aCGSue_kAAcWigzwBUk090.jpg" />
這些開啟軟體的是最基本的顯示,表徵圖和資料都來自於網路,每次滑動的時候都會不斷的下載表徵圖,下載在過的表徵圖他會再次在下載,這個體驗是非常不好的。所以我們在下載的表徵圖過後要把bitmap儲存起來,當已經下載過的就不要再下載,直接從容器裡面取。例如:Bitmap bitmap = imageBitmaplist.get(position);在圖片bitmap 下載完後就儲存起來,不過在我們下載的過程中是需要時間的。所以在現在中如果還是快速的上下滑動還是一樣會導致圖片多次下載,解決:因為我們在每次下載的時候都會new 出asyncTask 來對我們圖片進行下載,例如:MyAsyncTask asyncTask = new MyAsyncTask(image,position);所以我們讓new 出的asyncTask 進行有條件的執行,把每一行先對應的asyncTask 進行儲存。在每次要下在的時候先看一下容器裡面的asyncTask 是否存在,如果存在的話說明正在下載,我們就不用再進行對應的下載。例如:
Bitmap bitmap = imageBitmaplist.get(position);
if (bitmap==null) {
MyAsyncTask asyncTask = asyncTasklist.get(position);
if (asyncTask==null) {
asyncTask = new MyAsyncTask(image,position);
asyncTask.execute(imageUrllist.get(position));
asyncTasklist.put(position, asyncTask);
}
} else {
image.setImageBitmap(bitmap);
}
這樣子就可以在下載的時候避免多次下載表徵圖。
對listview的最佳化,在每次上下滑動的時候會每次產生一個新的View。所以要對View進行複用,可以用上一個消失的View convertView,來替換這個所要產生新的view。所以可以對convertView進行判斷,如果convertView要是為null 的時候我們才建立一個新的View 。要是不為空白的話,就直接拿起來複用,這丫可以解決資源問題,不會造成資源浪費。例如:
View inflate =null;
if (convertView==null) {
LayoutInflater layoutInflater = getLayoutInflater();
inflate = layoutInflater.inflate(R.layout.layout, null);
} else {
inflate=convertView;
}
和View 一樣,我們每次有聲明的一開始聲明的
ImageView image = (ImageView) inflate.findViewById(R.id.image);
ProgressBar progressBar1 = (ProgressBar) inflate.findViewById(R.id.progressBar1);
Button button1 = (Button) inflate.findViewById(R.id.button1);
TextView text = (TextView) inflate.findViewById(R.id.textView1);
幾個組件,也可以對其複用。把這些都放在一個class裡面需要的時候拿出來用就可以,例如:
View inflate =null;
Myview myview =null;
if (convertView==null) {
myview = new Myview();
LayoutInflater layoutInflater = getLayoutInflater();
inflate = layoutInflater.inflate(R.layout.layout, null);
myview.image = (ImageView) inflate.findViewById(R.id.image);
myview.progressBar1 = (ProgressBar) inflate.findViewById(R.id.progressBar1);
myview.button1 = (Button) inflate.findViewById(R.id.button1);
myview.text = (TextView) inflate.findViewById(R.id.textView1);
inflate.setTag(myview);
} else {
inflate=convertView;
myview=(Myview) inflate.getTag();
}
這樣的話可以進行多次複用。;
但是由於複用的關係,在每次圖片還在下載的過程是如果圖片在第一張下載完成後,後面的圖片還沒有下載的關係,進行上下的滑動。會發現,在發現在底下的時候有出現第一次的表徵圖,在過了一段時間後會發現圖片的跳變問題,這個就是因為view複用,例如第7行複用第0行的時候,第7行的表徵圖還沒有下載,原先應該是預設的原始圖片,但是由於在第0行的時候已經對表徵圖變更,他已經不是預設的表徵圖,所以會顯示之前的表徵圖,
解決:在一開始要下載表徵圖,更改圖片之前把圖片先改為我們預設的圖片,例如:
myview.image.setImageResource(R.drawable.ic_launcher);
這樣只能解決基本的問題,如果一開始只是輕輕滑動的話,是不會出現表徵圖閃變,如果要是一開始的時候在圖片還在下載的時候就進行快速的上下滑動的話,這樣還是會出現圖片閃跳。我們在輕輕滑動的時候他view 的替換是有規律的,但是如果開始滑動的時候view是沒有規律,他的出現時不定像的,即在滑動過程中,要對image進行替換。
例如:
public void changview(ImageView image)
{
this.image = image;
}
asyncTask.changview(myview.image);
並且在下載完圖片的時候,必須對當前行有顯示的才變更。
例如:
int fvp = mlistview.getFirstVisiblePosition();
int lvp = mlistview.getLastVisiblePosition();
if (position>=fvp&&position<=lvp) {
//儲存bitmap
imageBitmaplist.put(position, result);
image.setImageBitmap(result);
}
以上是開啟介面時候最基本的顯示,一切資料都來自與網路,接下來就是當我們點擊按鈕下載的時候,會進行基本的檔案下載,如同之前的圖片下載一樣,檔案下載是在點擊下載後檔案才會下載,所有操作如同上面圖片基本相同,唯一的就是在點擊下載的時候,檔案的進度條會跟隨的下載進度不斷的進行促發。這是需要用到的是onProgressUpdate();在用到onProgressUpdate的時候,資料下載進度是從publishProgress傳入;作業碼如;
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/73/6F/wKiom1X9mRmyI2cjAAE2eJkdH7g093.jpg" title="image_04.png" alt="wKiom1X9mRmyI2cjAAE2eJkdH7g093.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/73/6F/wKiom1X9mUTioybWAALjuMWqZ0o529.jpg" title="image_03.png" alt="wKiom1X9mUTioybWAALjuMWqZ0o529.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/73/6D/wKioL1X9m5DAVzM_AACk03kDOEc436.jpg" title="image_06.png" alt="wKioL1X9m5DAVzM_AACk03kDOEc436.jpg" />
問題:由於一開始的最佳化,對view,和基本組件的複用關係,導致了bug,在上下滑動的時候別的地方沒有點擊下載,他的ProgressBar中的進度條也是顯示滿格。
解決:
如同圖片的一樣,定義容器,用於儲存,儲存當前是否是在下載,下載中,下載成功的三個狀態,在對齊做對應的操作,並且與進行替換,作業碼如下:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/73/6D/wKioL1X9qNfQGjEaAAKZZjoCCS0407.jpg" style="float:none;" title="image07.png" alt="wKioL1X9qNfQGjEaAAKZZjoCCS0407.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/73/6F/wKiom1X9ppzR17gLAAJ87Xcweto030.jpg" style="float:none;" title="image_08.png" alt="wKiom1X9ppzR17gLAAJ87Xcweto030.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/73/6D/wKioL1X9qNjyRcf0AAHA9lV_MlM171.jpg" style="float:none;" title="image_09.png" alt="wKioL1X9qNjyRcf0AAHA9lV_MlM171.jpg" />
在這次的類比手機小幫手下載,已經基本上都完成了。
本文出自 “java” 部落格,轉載請與作者聯絡!
android之類比手機小幫手下載