学习andriod开发之 异步加载图片(二)--- 使用其他进度条
大家好 我是akira上一节 我们讲到使用AsyncTask 这个类进行异步的下载
主要是涉及到一些图片的更新 这次我们继续上一个demo的改进 。
不知道你是否发现一个问题 上一节我们遗留了两个bug 1 在无网络情况下 点击会崩
咱们说 软件开发最忌讳的就是crash 而这个是在bug解决方案中的一级要解决的 所以这个问题
必须搞定 2 就是我们会发现进度并未更新 而图片是显示完毕了的 3 就是一个扩展 这次我将会带来
daimajia的新库 也是做库小达人的最新作品 NumberProgressBar的使用。
1 首先 咱们问题一个一个的解决 首先是第一个 点击会崩溃 那我们就要清楚 why
也就是为什么点击会崩溃 解决这个问题的源头要从原来的代码看起
下面这段代码
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
学习andriod开发之 异步加载图片(二)--- 使用其他进度条的更多相关文章
- Android之使用Android-AQuery异步加载图片(一)
第一节:转载地址(http://www.cnblogs.com/lee0oo0/archive/2012/10/25/2738299.html) // 必须实现AQuery这个类 AQuery aq ...
- Android学习笔记(二)之异步加载图片
最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...
- IOS学习之路二十三(EGOImageLoading异步加载图片开源框架使用)
EGOImageLoading 是一个用的比较多的异步加载图片的第三方类库,简化开发过程,我们直接传入图片的url,这个类库就会自动帮我们异步加载和缓存工作:当从网上获取图片时,如果网速慢图片短时间内 ...
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...
- [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...
- 多线程异步加载图片async_pictures
异步加载图片 目标:在表格中异步加载网络图片 目的: 模拟 SDWebImage 基本功能实现 理解 SDWebImage 的底层实现机制 SDWebImage 是非常著名的网络图片处理框架,目前国内 ...
- Android之ListView异步加载图片且仅显示可见子项中的图片
折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...
- wemall app商城源码中基于JAVA的Android异步加载图片管理器代码
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...
随机推荐
- Java EE javax.servlet中的ServletContext接口
ServletContext接口 public interface ServletContext (https://docs.oracle.com/javaee/7/api/javax/servlet ...
- [C#]使用BackgroudWorker刷新UI延迟的解决方法
今天使用BackgroundWorker刷新UI发生延时现象,找了好久才发现AutoResetEvent可以解决,代码如下 private void BgWorker_ProgressChanged( ...
- 关于mysql事务的几件小事
零.MyISAM和InnoDB关于锁的区别 ①MyISAM默认用的是表级锁,不支持行级锁. ②InnoDB默认用的是行级锁,也支持表级锁. ③共享锁和排它锁的兼容性 |X|排它锁|共享锁| -|-|- ...
- django 上传路径至vue处理组件加载
1,在主目录(项目目录)下新建中间件middleware.py文件 写入 from django.utils.deprecation import MiddlewareMixin from djang ...
- git commit报错解决,绕过代码检查
上一个项目用的svn,新项目用了git,很开心,终于学习了git了,本以为把git都学会了,但是还是遇到了一个不在自己学习的知识点范围内的问题,最后是同事帮忙解决的. 问题:第一次代码commit的时 ...
- spring整合shiro配置BUG,Tomcat启动不了:Error during artifact deployment. See server log for details
现象 spring配置shiro权限控制之后,项目无法启动 [2019-08-09 09:00:35,800] Artifact export_web_manager:war exploded: Er ...
- MySQL查询多行重复数据SQL
1 详见如下 SELECT day_time,`city_code`,count(1) as num FROM t_user_register_analyse GROUP BY `day_time`, ...
- 抓住“新代码”的影子 —— 基于GoAhead系列网络摄像头多个漏洞分析
PDF 版本下载:抓住“新代码”的影子 —— 基于GoAhead系列网络摄像头多个漏洞分析 Author:知道创宇404实验室 Date:2017/03/19 一.漏洞背景 GoAhead作为世界上最 ...
- 网络初级篇之RSTP(原理与配置)
一.RSTP的产生 前面的文章写到了当网络拓扑发生变化时,STP的收敛速度大约需要花费30秒-50秒的时间才会继续转发数据.这样在实际生产环境中花费的时间是非常长的,这样RSTP(快速生成树协议)便应 ...
- Java的概述
Java的基本概述 Java是SUN(Stanford University Network),斯坦福大学网络公司)1995年推出的一门高级编程语言.Java是一种面向Internet的编程语言.随着 ...