• 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

  • 相关阅读:
    通过vue-cli命令行安装uni-app
    微信小程序中父子通信
    react启动问题
    react 父子通信
    windows下MongoDB的安装和启动服务--转载
    vue中使用骨架 vue-skeleton-webpack-plugin
    像企业一样思考
    Promise原理详解
    如何封装一个Cookie库
    你应该知道的浏览器缓存知识
  • 原文地址:https://www.cnblogs.com/Sharley/p/5353406.html
Copyright © 2020-2023  润新知