Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 學習andriod開發之 異步加載圖片(二)--- 使用其他進度條

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

編輯:關於Android編程

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

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

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

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

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

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

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

也就是為什麼點擊會崩潰 解決這個問題的源頭要從原來的代碼看起

下面這段代碼

 

 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的實例化

 

WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);
wifiState =  manager.getWifiState();//wifi狀態
第一段代碼適用於很多的manager 比如inputmanager actvitymanager 等等

 

而第二句就是很多人想要的那個狀態 究竟是不是想要的呢 我們繼續往下看

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

 

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的狀態 你還需要加上權限

如下

 

 
    

但是 根本的問題還是沒解決呀

 

所以 別懷疑了 咱從頭來過吧

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

咱來看看

 

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

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

 

 

mInfo.isAvailable()

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

 

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

要進行並且的判斷

並且去設置按鈕是否為可點

 

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 來看關鍵代碼

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了麼 那個就是刷新方法

 

@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代碼

 



    

這裡面 你會發現 我的custom命名空間沒有用到 為毛 因為我把有些東西全部用一個style代表了

 

不行你看

 


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

 

所以直接用就可以了

main代碼修改

 

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代碼修改

 

 

/**
 * Created by akira on 2015/1/27.
 */
public class ImageDownloadTask extends AsyncTask {
    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();
    }
}
究竟行不行 來運行運行吧

 

\
 

什麼 你沒看起清楚? 沒事 onemoretime!

\

OK 三個問題搞定 下一次 咱們來動態設置progress的style 以及寫一個自己的progressbar

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved