編輯:關於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);
mInfo.isAvailable()
然後 你想怎麼做 是判斷當前網絡可用就點擊麼 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; } }
最後 刷新 看到那個publishProgress了麼 那個就是刷新方法
@Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress[0]); mBar.setProgress(progress[0]); Log.e(akira,progress[0]+...); }
下面我用log打印了下 不打印無所謂
最後post方法沒修改
3
daimajia的庫 首先 我們需要找到daimajia的庫
以下url
https://github.com/daimajia/NumberProgressBar
寫的已經非常非常非常清楚了
Eclipse和andriodstudio都有各自的導入方式 就不贅述了
有些如果你發現你導入之後 找不到style 你可以手動去拷它裡面的樣式
下面是我的layout代碼
不行你看
所以直接用就可以了
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(); } } }
/** * 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
今天看了鴻洋_大神在慕課網講的qq5.0側滑菜單。學了不少的知識,同時也佩服鴻洋_大神思路的清晰。看了教程課下也自己實現了一下。代碼幾乎完全相同 別噴我啊。。沒辦法 o(
開發環境:android4.1.1實驗功能:在第一個Hello World!為標簽的activity中顯示good,該界面中有一個名為Next的按鈕。點擊Next按鈕進入
Activities提供了一種方便管理的創建、保存、回復的對話框機制,例如 onCreateDialog(int), onPrepareDialog(int, Dialo
本文實例講述了Android編程之頁面切換測試。分享給大家供大家參考。具體分析如下:一、軟件平台:win7 + eclipse + sdk二、設計思路:兩個頁面:mian