學習andriod開發之 異步加載圖片(二)--- 使用其餘進度條

你們好 我是akira上一節 咱們講到使用AsyncTask 這個類進行異步的下載css

主要是涉及到一些圖片的更新 此次咱們繼續上一個demo的改進 。html

不知道你是否發現一個問題 上一節咱們遺留了兩個bug 1 在無網絡狀況下 點擊會崩java

我們說 軟件開發最忌諱的就是crash 而這個是在bug解決方案中的一級要解決的 因此這個問題android

必須搞定 2 就是咱們會發現進度並未更新 而圖片是顯示完畢了的 3 就是一個擴展 此次我將會帶來git

daimajia的新庫 也是作庫小達人的最新做品 NumberProgressBar的使用。github

1 首先 我們問題一個一個的解決 首先是第一個 點擊會崩潰 那咱們就要清楚 whyapi

也就是爲何點擊會崩潰 解決這個問題的源頭要從原來的代碼看起數組

下面這段代碼緩存

 

?
1
2
3
4
5
6
7
8
try
            HttpURLConnection connection = (HttpURLConnection) imageUrl.openConnection(); 
            connection.setDoInput( true ); 
            connection.connect(); 
            inputStream =  connection.getInputStream(); 
            downloadImg =  BitmapFactory.decodeStream(inputStream); 
  
        }

其實 咱們一眼就能看出來 其實就是你若是沒網就拿不到流 由於我是沒作過圖片緩存的 也就是說 每次點擊都會去get網絡

 

沒有流 就會形成 inputstream爲null 而 再去加載一個null 天然而然 就XXX了 因此 咱們找到根源 就是要判斷獲得的流是否爲null

但 僅僅如此麼 顯然不是 咱們最好從源頭找到爲何沒網 或者說是一個有網的監聽 這樣最好

說到網 有人天然會想到wifi 說道wifi有人天然會想固然是去想到一個類叫作wifiManager 好 我就知足你的需求

來解析下wifiManager會不會提供一個有沒有網的方法 來去判斷

先看下wifiManager的實例化

 

?
1
2
WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);
wifiState =  manager.getWifiState(); //wifi狀態

第一段代碼適用於不少的manager 好比inputmanager actvitymanager 等等

 

而第二句就是不少人想要的那個狀態 到底是不是想要的呢 咱們繼續往下看

這裏面的狀態 我也寫下來了

 

?
1
2
3
4
5
private  final int  WIFI_STATE_DISABLING = 0 ; //表示停用中。
     private  final int  WIFI_STATE_DISABLED  = 1 ; //表示不可用。
     private  final int  WIFI_STATE_ENABLING  = 2 ; //表示啓動中。
     private  final int  WIFI_STATE_ENABLED   = 3 ; //表示準備就緒。
     private  final int  WIFI_STATE_UNKNOWN   = 4 ; //表示未知狀態。

看到這個你會想到什麼 我第一眼想到的是我本身的網件路由器 這尼瑪就是一個網絡的加載過程 並且仍是wifi的

 

咱們發現最靠譜的啓動中彷佛也不能知足咱們的需求 這個時候有些人也許開始懷疑人生 忘了說

若是你想監聽wifi的狀態 你還須要加上權限

以下

 

?
1
2
<uses-permission android:name= "android.permission.ACCESS_WIFI_STATE" >
    <uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" ></uses-permission></uses-permission>


可是 根本的問題仍是沒解決呀

 

因此 別懷疑了 咱從頭來過吧

這個時候 有人提到了 ConnectivityManager 咦? 這個行不行呢

咱來看看

 

?
1
2
ConnectivityManager cManager =  (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo mInfo =  cManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);


yahoo!!! 不錯 看起來挺靠譜 繼續往下深究

 

 

?
1
mInfo.isAvailable()


這個api就是告訴你網絡是否可用 前面那個type有不少 這裏面就說了wifi的 都比較簡單 咱就不去官網看了

 

而後 你想怎麼作 是判斷當前網絡可用就點擊麼 nono 萬一url爲空怎麼辦 考慮到嚴謹性和代碼的健壯性 我們

要進行而且的判斷

而且去設置按鈕是否爲可點

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Button downBtn = (Button) findViewById(R.id.downBtn);
         if (mInfo.isAvailable() && !TextUtils.isEmpty(url)){
                 downBtn.setClickable( true );
                 downBtn.setOnClickListener( new View.OnClickListener() {
                 @Override
                 public void onClick(View view) {
                     new ImageDownloadTask(MainActivity. this ,img,bar).execute(url);
 
                 }
              });
         } else {
             downBtn.setClickable( false );
             downBtn.setOnClickListener( null );
             Toast.makeText(MainActivity. this ,當前無wifi,Toast.LENGTH_SHORT).show();
         }



 

OK 外面的邏輯 我們處理完了 解決了1 crash

PS: 其實這裏解決網絡很不專業 通常在正式項目裏 咱們都會寫一個廣播接受 去觀察網絡是否可用 這個放到之後

廣播的時候再講

2 關於更新進度 首先 我很清楚一點 若是我要更新一個進度 我確定要知道一個

總進度 一個當前進度 還有一個通知其刷的這麼一個方法

OK 來看關鍵代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int totalLength; //總共長度
         URL imageUrl = null ; //圖片的url
         int length = - 1 ;
         InputStream inputStream = null ;
         try {
             imageUrl = new URL(params[ 0 ]);
             HttpURLConnection connection = (HttpURLConnection) imageUrl.openConnection();
             connection.setDoInput( true );
             connection.connect();
             inputStream =  connection.getInputStream();
             totalLength = connection.getContentLength();
             if (inputStream!= null ){
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 byte [] buffer = new byte [ 1024 ];
                 int count = 0 ;
                 while ((length = inputStream.read(buffer)) != - 1 ) {
                     baos.write(buffer, 0 , length);
                     count += length;
                     //這句通知upXXX更新進度
                     publishProgress(( int ) ((count / ( float ) totalLength) * 100 ));
                 }
                 byte [] data=baos.toByteArray(); //聲明字節數組
                 downloadImg=BitmapFactory.decodeByteArray(data, 0 , data. length);
                 return ok;
             }
         }


這裏面 咱用一個流去寫 而後加載的時候從流利去拿 而總長度有一個getContentLength的方法

 

最後 刷新 看到那個publishProgress了麼 那個就是刷新方法

 

?
1
2
3
4
5
6
@Override
     protected void onProgressUpdate(Integer... progress) {
           super .onProgressUpdate(progress[ 0 ]);
           mBar.setProgress(progress[ 0 ]);
           Log.e(akira,progress[ 0 ]+...);
     }


一樣 這裏進行刷新 注意 progress是一個可變數組

 

下面我用log打印了下 不打印無所謂

最後post方法沒修改

3

daimajia的庫 首先 咱們須要找到daimajia的庫

如下url

https://github.com/daimajia/NumberProgressBar

寫的已經很是很是很是清楚了

Eclipse和andriodstudio都有各自的導入方式 就不贅述了

有些若是你發現你導入以後 找不到style 你能夠手動去拷它裏面的樣式

下面是個人layout代碼

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<relativelayout android:layout_height= "match_parent" android:layout_width= "match_parent" tools:context= ".MainActivity" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:custom= "http://schemas.android.com/apk/res-auto" xmlns:tools= "http://schemas.android.com/tools" >
 
     <textview android:id= "@+id/hello" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:text= "@string/hello_world" ><button android:id= "@+id/downBtn" android:layout_below= "@id/hello" android:layout_height= "wrap_content" android:layout_width= "match_parent" android:text= "down" android:textcolor= "@android:color/black" android:textsize= "20sp" >
 
     <imageview android:id= "@+id/img" android:layout_below= "@id/downBtn" android:layout_centerinparent= "true" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:scaletype= "fitXY" android:visibility= "gone" >
 
     <com.daimajia.numberprogressbar.numberprogressbar android:id= "@+id/bar" android:layout_centerinparent= "true" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:visibility= "gone" style= "@style/NumberProgressBar_Funny_Orange" >
     <!--<ProgressBar
         android:id=@+id/bar
         android:layout_centerInParent= true
         android:layout_width=wrap_content
         android:layout_height=wrap_content
         android:visibility=gone
         />-->
 
</com.daimajia.numberprogressbar.numberprogressbar></imageview></button></textview></relativelayout>


這裏面 你會發現 個人custom命名空間沒有用到 爲毛 由於我把有些東西所有用一個style表明了

 

不行你看

 

?
1
2
3
4
5
6
7
8
9
10
<style name= "NumberProgressBar_Funny_Orange" type= "text/css" ><item name=android:layout_height>wrap_content</item>
         <item name=android:layout_width>match_parent</item>
         <item name=max> 100 </item>
         <item name=progress> 0 </item>
         <item name=progress_unreached_color>#CCCCCC</item>
         <item name=progress_reached_color>#FF530D</item>
         <item name=progress_text_size>10sp</item>
         <item name=progress_text_color>#FF530D</item>
         <item name=progress_reached_bar_height> 1 .5dp</item>
         <item name=progress_unreached_bar_height> 0 .75dp</item></style>


這裏面 你會發現 他定義了 寬高 max 進度 顏色 和字體顏色 大小等等

 

因此直接用就能夠了

main代碼修改

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MainActivity extends Activity {
     String url ;
     private  final int  WIFI_STATE_DISABLING = 0 ; //表示停用中。
     private  final int  WIFI_STATE_DISABLED  = 1 ; //表示不可用。
     private  final int  WIFI_STATE_ENABLING  = 2 ; //表示啓動中。
     private  final int  WIFI_STATE_ENABLED   = 3 ; //表示準備就緒。
     private  final int  WIFI_STATE_UNKNOWN   = 4 ; //表示未知狀態。
     private  NetworkInfo mInfo;
     private ConnectivityManager cManager;
     private Button downBtn;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         if (TextUtils.isEmpty(url))
             url = http: //bbra.cn/Uploadfiles/imgs/20110303/fengjin/015.jpg;
         final NumberProgressBar bar = (NumberProgressBar) findViewById(R.id.bar);
         final ImageView img = (ImageView) findViewById(R.id.img);
         final WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);
         int wifiState =  manager.getWifiState(); //wifi狀態
         cManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
         mInfo =  cManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         downBtn = (Button) findViewById(R.id.downBtn);
         if (mInfo.isAvailable() && !TextUtils.isEmpty(url)){
                 downBtn.setClickable( true );
                 downBtn.setOnClickListener( new View.OnClickListener() {
                 @Override
                 public void onClick(View view) {
                     new ImageDownloadTask(MainActivity. this ,img,bar).execute(url);
 
                 }
              });
         } else {
             downBtn.setClickable( false );
             downBtn.setOnClickListener( null );
             Toast.makeText(MainActivity. this ,當前無wifi,Toast.LENGTH_SHORT).show();
         }
 
     }
 
 
}


ImageDownXXX代碼修改

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
  * Created by akira on 2015/1/27.
  */
public class ImageDownloadTask extends AsyncTask<string,integer,string> {
     private Bitmap downloadImg;
     private NumberProgressBar mBar;
     private Context mContext;
     private ImageView netImageView;
     private int perPro; //遞增的進度
     public ImageDownloadTask(Context context, ImageView imageView, NumberProgressBar bar){
         this .mContext = context;
         this .netImageView = imageView;
         this .mBar = bar;
         mBar.incrementProgressBy(perPro);
     }
 
     @Override
     protected void onPreExecute() {
//        super.onPreExecute();
         mBar.setVisibility(View.VISIBLE);
     }
 
     @Override
     protected String doInBackground(String... params) {
         int totalLength; //總共長度
         URL imageUrl = null ; //圖片的url
         int length = - 1 ;
         InputStream inputStream = null ;
         try {
             imageUrl = new URL(params[ 0 ]);
             HttpURLConnection connection = (HttpURLConnection) imageUrl.openConnection();
             connection.setDoInput( true );
             connection.connect();
             inputStream =  connection.getInputStream();
             totalLength = connection.getContentLength();
             if (inputStream!= null ){
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 byte [] buffer = new byte [ 1024 ];
                 int count = 0 ;
                 while ((length = inputStream.read(buffer)) != - 1 ) {
                     baos.write(buffer, 0 , length);
                     count += length;
                     //這句通知upXXX更新進度
                     publishProgress(( int ) ((count / ( float ) totalLength) * 100 ));
                 }
                 byte [] data=baos.toByteArray(); //聲明字節數組
                 downloadImg=BitmapFactory.decodeByteArray(data, 0 , data. length);
                 return ok;
             }
         } catch (MalformedURLException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             try {
                 inputStream.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
 
         return null ;
     }
 
     @Override
     protected void onProgressUpdate(Integer... progress) {
           super .onProgressUpdate(progress[ 0 ]);
           mBar.setProgress(progress[ 0 ]);
           Log.e(akira,progress[ 0 ]+...);
     }
 
 
     @Override
     protected void onPostExecute(String result) {
//        super.onPostExecute(s);
          mBar.setVisibility(View.GONE);
          netImageView.setVisibility(View.VISIBLE);
          netImageView.setImageBitmap(downloadImg);
          Toast.makeText(mContext,加載完畢,Toast.LENGTH_LONG).show();
     }
}</string,integer,string>

究竟行不行 來運行運行吧

 

結伴旅遊,一個免費的交友網站:www.jieberu.com

推推族,免費得門票,遊景區:www.tuituizu.com

相關文章
相關標籤/搜索