学习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:[email protected]+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

时间: 2024-10-14 06:29:25

学习andriod开发之 异步加载图片(二)--- 使用其他进度条的相关文章

学习andriod开发之 异步加载图片--- 使用系统进度条

大家好 我是akira 学习图片异步加载的例子 说道这里有人可能要问了 什么是异步 为什么要用异步 why? 说白了很简单 省时间 省资源 我举个例子你就懂了 比如你在下东西 至于下什么 那些邪恶的骚年们又要YY了 不去管他们.比如你在下东西 这个时候 另外一个人也在下同一个东西 那么那个人怎么办 他就等你下完 等到天荒地老?ありえないこと impossible 他肯定也要下 那么问题就来了 他如何下?这个时候就要用到异步 说道这里 有人可能问什么叫同步 什么叫异步 我在这里在给大家举一个简单的

android开发干货:实现listview异步加载图片

针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师说凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.net.

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

转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠.另外,Android 3.0

[原创]cocos2dx加载网络图片&amp;异步加载图片

[动机] 之前看到一款卡牌游戏,当你要看全屏高清卡牌的时候,游戏会单独从网络上下载,本地只存了非高清的,这样可以省点包大小,所以我萌生了实现一个读取网络图片的类. [联想] 之前浏览网页的时候经常看到一张图片渐进(由模糊变清晰)的显示,如果在游戏中,诸如像显示高清卡牌的时候,使用有这种方式去显示一张图片,这样的体验应该会稍微好些 [相关知识] png interlaced:png图片在导出的时候是可以选择 interlaced (Adam7)的,这样的存储的png在网页上显示会渐进显示, 这种i

Android ListView异步加载图片乱序问题,原因分析及解决方案

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android所有系统自带的控件当中,ListView这个控件算是用法比较复杂的了,关键是用法复杂也就算了,它还经常会出现一些稀奇古怪的问题,让人非常头疼.比如说在ListView中加载图片,如果是同步加载图片倒还好,但是一旦使用异步加载图片那么问题就来了,这个问题我相信很多Android开发者都曾经遇到过,就是异步加载图片会出现错位乱序的情况.遇到这个问题时,不

Android 实现异步加载图片

麦洛开通博客以来,有一段时间没有更新博文了.主要是麦洛这段时间因项目开发实在太忙了.今天周六还在公司加班,苦逼程序猿都是这样生活的. 今天在做项目的时候,有一个实现异步加载图片的功能,虽然比较简单但还是记录一下吧.因为麦洛之前实现异步加载图片都是使用了AsynTask这个API,继续这个类,实现起来非常简单也很方便.在doInBackground()方法里实现下载逻辑.具体实现如下 实现逻辑是:先从内存中读取,如果内存中有这张图片,则直接使用;如果内存没有再到sdcard上读取,如果有则显示;如

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

折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整实例都没看到,只有自己一点点研究了,总体感觉 android 下面要显示个图片真不容易啊. 项目主要实现的功能: 异步加载图片图片内存缓存.异步磁盘文件缓存解决使用 viewHolder 后出现的图片错位问题优化列表滚动性能,仅显示可见子项中的图片无需固定图片显示高度,对高度进行缓存使列表滚动时不会

android实用技巧:android实现listview异步加载图片

针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师说凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.net.

Android:ViewPager扩展详解——带有导航的ViewPagerIndicator(附带图片缓存,异步加载图片)

大家都用过viewpager了, github上有对viewpager进行扩展,导航风格更加丰富,这个开源项目是ViewPagerIndicator,很好用,但是例子比较简单,实际用起来要进行很多扩展,比如在fragment里进行图片缓存和图片异步加载. 下面是ViewPagerIndicator源码运行后的效果,大家也都看过了,我多此一举截几张图: 下载源码请点击这里 ===========================================华丽的分割线==============