Android异步加载

Android异步加载

 

一、为什么要使用异步加载?

       1.Android是单线程模型

    2.耗时操作阻碍UI线程

二、异步加载最常用的两种方式

     1.多线程、线程池

  2.AsyncTask

三、实现ListView图文混排

3-1 实现读取网页中的json数据到ListView中 (图片首先为默认图片)

      3.1.1:主布局只有一个ListView和一个listView_item的布局

      3.1.2:网页json数据的链接(http://www.imooc.com/api/teacher?type=4&num=30),打开后为json数据,开发者可以通过使用Json格式化工具进行清楚的查看json数据的信息

      3.1.3:书写解析网页JSON数据的代码

思路解析:

    1) 一个内部类继承AsyncTask,书写未实现的方法,其中在方法中有一个doBackground()方法,在其方法中书写得到Json数据的方法

   2) 书写通过inputStream解析网页所返回的数据,只有拿到网页中的json数据才能实现解析的操作

   3)将url对应的json数据转换为我们所封装的NewsBean对象,在这个方法中,我们通过第二步拿到了json数据,然后进行json数据的解析,并且封装到实体类对象中,这样你的实体类中就有解析的json数据了

  4)创建ListView的适配器

  5)在继承AsyncTask的类中书写onPostExecute()方法,在这个方法中,实现绑定适配器,加载数据源的操作

  6)在onCreate方法中执行这个异步操作:new NewAsyncTask().execute(URL);并且传入url地址

  7)在清单文件中添加联网权限 <use-permission  android:name="android.permission.INTERNET"/>

3-2  实现在ListView中添加网络中图片

  &由于加载图片是一种耗时操作,所以我们可以通过新建Thread的方法或者继承AsyncTask来实现

  3.2.1:我们通过新线程的方式来实现加载网络图片,新建ImageLoader.java

  思路解析:

    1)新建一个线程来实现加载图片

    2)创建加载图片的方法,方法的参数为图片的url,这个url可以通过解析刚才的json数据得到

1
HttpURLConnection connection=(HttpURLConnection) url.openConnection(); //打开链接   //注意是:HttpURLConnection而不是HttpsURLConnection

     通过这条语句,将连接转化成流,然后得到流,最后将流转换为bitmap对象

    3)得到bitmap对象后,我们新建Handler线程,在这个线程中进行图片的更换,由于bitmap在我们的新线程中,所以我们通过handler的消息传递进行将bitmap对象传入到主线程中去

   4)由于ListView的缓存机制,所以我们通过在适配器为图片设置tag的方法从而实现图片的正确加载,避免导致图片的来回替换

    在Handler中,我们通过通过设置判断tag属性,来判断图片的url是否相等

    附录:ListView适配器的代码:

 

    3.2.2 :我们通过使用继承AsyncTask的方法来实现图片的异步加载

首先我们需要创建一个方法:showImageByAsyncTask,并且传入值为ImageView以及图片的url

   其次新建一个类继承AsyncTask,这个类为匿名内部类,为ImageLoder中的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap>{
        private ImageView mImageView;
        private String mUrl;
        public NewsAsyncTask(ImageView imageView,String url){
            mImageView=imageView;
            mUrl=url;
        }
        @Override
        protected Bitmap doInBackground(String... params) {
            return getBitmapFromURL(params[0]);
        }
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if(mImageView.getTag().equals(mUrl)){
                 mImageView.setImageBitmap(bitmap); 
            }
        }
    }

    然后仅仅需要修改NewsAdapter中为图片控件赋值的代码即可:

1
2
//new ImageLoader().showImageByThread(viewHolder.ivIcon,url);  //图片id,图片的链接  --->>使用多线程的方法
new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon,url);  //使用继承AsyncTask的方式实现图片的异步加载

  至此,我们为控件赋值以及异步加载数据的功能已经实现,我们来看下效果:

  

 

四、LruCache缓存机制(使用内存空间换取效率)

       问题分析:上述的程序中存在一个问题,问题是当用户每次刷新的时候,都需要从网络中读取数据并且进行加载,所以这样增加了用户的流量费用,不利于用户的使用

      那么如何提高用户的体验??---->>>>使用缓存

      Lru算法:

        Lru:Least Recently Used 近期最少使用算法

       Android提供了LruCache类来实现这个缓存算法

  思路:1.声明LruCache对象

            2.在构造方法中实现创建LruCache对象,在这里需要实现它的一个内部方法,用于告诉系统图片的大小,在此之前,你需要得到运行的最大内存,然后用最大内存的一部分

          3.添加两个方法:一个将图片加入到缓存,一个从缓存中读取图片

                      ---->>将图片加入到缓存,从网络中读取数据,如果图片不为空,则加入到缓存

                      ----->>从缓存中读取图片,通过键值对的形式读取图片

         4.在异步加载图片的使用,首先需要从缓存中读取图片,如果图片为空的话,加载图片,加载出来的图片添加到缓存中

         5.在adapter中创建ImageLoader对象,实现添加适配器的时候自动加载缓存机制

    附:代码

 

五:源代码下载:

      https://github.com/monsterLin/Async_ListView

posted @ 2016-04-04 23:34  Sharley  阅读(301)  评论(0编辑  收藏  举报