大家好 我是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开发之 异步加载图片(二)--- 使用其他进度条的更多相关文章

  1. Android之使用Android-AQuery异步加载图片(一)

    第一节:转载地址(http://www.cnblogs.com/lee0oo0/archive/2012/10/25/2738299.html) // 必须实现AQuery这个类 AQuery aq ...

  2. Android学习笔记(二)之异步加载图片

    最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...

  3. IOS学习之路二十三(EGOImageLoading异步加载图片开源框架使用)

    EGOImageLoading 是一个用的比较多的异步加载图片的第三方类库,简化开发过程,我们直接传入图片的url,这个类库就会自动帮我们异步加载和缓存工作:当从网上获取图片时,如果网速慢图片短时间内 ...

  4. Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...

  5. [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

    转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...

  6. 多线程异步加载图片async_pictures

    异步加载图片 目标:在表格中异步加载网络图片 目的: 模拟 SDWebImage 基本功能实现 理解 SDWebImage 的底层实现机制 SDWebImage 是非常著名的网络图片处理框架,目前国内 ...

  7. Android之ListView异步加载图片且仅显示可见子项中的图片

    折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...

  8. wemall app商城源码中基于JAVA的Android异步加载图片管理器代码

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

  9. Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法

    Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...

随机推荐

  1. mybatis+oracle批量插入报不符合协议和sql未正确结束

    在Java中循环save,需要加useGeneratedKeys="false",否则报错不符合协议 mybatis批量插入,也需要在insert里加入 useGeneratedK ...

  2. 进阶Java编程(9)反射与类操作

    1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...

  3. C#异步编程学习笔记之-async和await(续)

    书接上文,本篇主要记录的内容要点:1.针对async和await在实际应用中的使用方式:2.异步方法返回值(有返回值和无返回值)的两种情况: 示例一(无返回值): using System; usin ...

  4. 安装多个ORACLE导致多个Oracle HOME的情况!

    Oracle由于版本的不同,在注册表中产生的注册表信息也有所不同,但主要的键值信息还是一样的,例如Oracle10g比oracle9i在注册表中表现的更为“简洁”,在未知的情况下,获取Oracle10 ...

  5. O033、Terminate Instance 操作详解

    参考https://www.cnblogs.com/CloudMan6/p/5486066.html   本节通过日志详细分析 Nova Terminate 操作.Terminate 操作就是删除 i ...

  6. springMVC基础框架搭建

    1.导入springMVC相关jar包: 2.添加Web.xml配置文件中关于SpringMVC的配置 <servlet> <servlet-name>springmvc< ...

  7. 不支持javascript的浏览器将JS脚本显示为页面内容

    不支持javascript的浏览器将JS脚本显示为页面内容.为了防止这种情况发生,您可以使用这样的HTML注释标记:<html ><体><script type=“tex ...

  8. java技术面试之面试题大全

    转载自:http://blog.csdn.net/lijizhi19950123/article/details/77679489 Java 面试知识点总结 本篇文章会对面试中常遇到的Java技术点进 ...

  9. A query was run and no Result Maps were found for...原来是mapper.xml文件出了问题,是使用MyBatis最常见的一种错误

    今天遇到一个问题,原来是mapper.xml文件出了问题,是使用MyBatis最常见的一种错误 报错的结果是这样的: A query was run and no Result Maps were f ...

  10. python之字典二 内置方法总结

    Python字典包含了以下内置方法: clear()函数用于删除字典内所有元素 dict1 = {, 'Class': 'First'} print('the start len %d' % len( ...