zoukankan      html  css  js  c++  java
  • ListView的网络加载(使用LRU缓存,滚动监听器)

    public class MainActivity extends AppCompatActivity {
        private List<Newsbeans> mlist;
        private static  String url="http://www.imooc.com/api/teacher?type=4&num=30";
        private ListView listView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Myaysctask myaysctask=new Myaysctask();
            //将url传递进去实现对于url的异步访问
            new Myaysctask().execute(url);
            listView= (ListView) findViewById(R.id.listview);
        }
        //将url转化为我们所需要的json对象
        private List<Newsbeans> getjsondata(String url){
            //初始化list
            mlist=new ArrayList<>();
            JSONObject jsonObject;
            Newsbeans newsbeans;
            try {
                //获取字节流
                String jsonstring= readStream(new URL(url).openStream());
                //将传入的字节流转化为json对象
                jsonObject=new JSONObject(jsonstring);
                //得到json下的data下的数组
                JSONArray jsonArray=jsonObject.getJSONArray("data");
    
                for(int i=0;i<jsonArray.length();i++){
                    //遍历json数组的到jsonobject的值
                    jsonObject=jsonArray.getJSONObject(i);
                    newsbeans=new Newsbeans();
                    //将jsonobject中的值赋予到已经封装好的值之中,通过getString方法获得
                    newsbeans.newscontent=jsonObject.getString("description");
                    newsbeans.newspic=jsonObject.getString("picSmall");
                    newsbeans.newstitle=jsonObject.getString("name");
                    //将newsbeans添加到list之中
                    mlist.add(newsbeans);
                }
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            }
            return mlist;
        }
        private String readStream(InputStream is){
            String result="";
            String line="";
            try {
                //将inputstream传入的为字节流,通过inputstreamreader将字节流转换为字符流
                InputStreamReader irs=new InputStreamReader(is,"utf-8");
                //通过bufferedreader将输入流读取出来
                BufferedReader br= new BufferedReader(irs);
                while ((line= br.readLine())!=null){
                    result+=line;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return result;
        }
        class Myaysctask extends AsyncTask<String,Void,List<Newsbeans>>{
    
            @Override
            //进行所有的耗时操作但不包括更改UI
            protected List<Newsbeans> doInBackground(String... strings) {
                //将string数组中的0位返回也就是传入url
                return getjsondata(strings[0]);
            }
    
            @Override
            protected void onPostExecute(List<Newsbeans> newsbeans) {
                Myadapter myadapter=new Myadapter(MainActivity.this,newsbeans,listView);
                listView.setAdapter(myadapter);
                super.onPostExecute(newsbeans);
            }
        }
    }

    在mainactivity中从网络中获取JSON数组,并转化为JSON对象,通过AsyncTask使用异步线程下载数据,并封装在已经设置好的空间中以及在子线程中设置UI,通过Myadapter对象传递参数用于在BaseAdapter中设置监听事件和设置ListView

    public class ImageviewHolder {
             //设置全局变量
             private String mURL;
             private LruCache<String,Bitmap> mCache;
             private Set<MyAsynctask> mTask;
             private ListView mListView;
    
    
        public ImageviewHolder(ListView listview){
            //在构造方法中初始化LruCache
            mListView=listview;
            mTask=new HashSet<>();
            //获取当前系统的最大的运行内存
            int MaxMem= (int) Runtime.getRuntime().maxMemory();
            //设置当前的缓存的内存
            int CacheMem=MaxMem/2;
            mCache=new LruCache<String,Bitmap>(CacheMem){
                //重写sizeof方法,获取缓存图片的大小
                @Override
                protected int sizeOf(String key, Bitmap value) {
                    return value.getByteCount();
                }
            };
        }
        private void addBitMapToCache(String url,Bitmap bitmap){
            //自定义方法,在判断所需的图片没有在缓存中存在的时候,将其放入到缓存之中
            if(getBitMapFromCache(url)==null){
                mCache.put(url,bitmap);
            }
    
        }
        private Bitmap getBitMapFromCache(String url){
            return mCache.get(url);
    
        }
        public void showImageBy(ImageView imageView,String mURL)  {
            Bitmap bitmap= getBitMapFromCache(mURL);
            /*
            * 判断在缓存中的图片是否存在,如果不存在则通过网络下载图片,其实这个方法在设定onScrollListener之后的作用
            * 已经失效了,只是作为一个在没有加载的时候初始化图标的功能。
            * */
            if (bitmap==null){
                imageView.setImageResource(R.mipmap.ic_launcher);
            }else {
                imageView.setImageBitmap(bitmap);
            }
        }
        public void imageLoder(int start,int end){
            //传递进来新的参数,在当前屏幕上的第一个和最后一个的可见项
            for (int i=start;i<end;i++){
                //获取到从第一个开始到最后一个结束的图片所对应的一个url,并对每一个url进行判断
                String url=Myadapter.mURLs[i];
                //加载我们所定义的一组imageview
                Bitmap bitmap= getBitMapFromCache(url);
                //判断在缓存中的图片是否存在,如果不存在则通过网络下载图片
                if (bitmap==null){
                    MyAsynctask task =new MyAsynctask(url);
                    task.execute(url);
                    //将task对象放入一个set集合之中,统一的做管理,如果listview不在滚动的时候就将其全部取消加载
                    mTask.add(task);
                }else {
                    ImageView imageView= (ImageView) mListView.findViewWithTag(url);
                    imageView.setImageBitmap(bitmap);
    
                }
            }
    
        }
        public void cancelTask(){
            if (mTask!=null){
                for (MyAsynctask task:mTask){
                    task.cancel(false);
                }
            }
        }
        public Bitmap getbitmapstream(String bitmapurl) throws IOException {
            InputStream is=null;
                //指向互联网资源的指针
                URL url=new URL(bitmapurl);
                //打开连接,并强行转换格式
                HttpURLConnection connection= (HttpURLConnection) url.openConnection();
                //获取输入的数据流
                is=new BufferedInputStream(connection.getInputStream());
                //解析所传入的数据
                Bitmap bitmap= BitmapFactory.decodeStream(is);
                //断开连接
                connection.disconnect();
                return bitmap;
        }
               public class MyAsynctask extends AsyncTask<String,Void,Bitmap>  {
                   //通过AsyncTask通过网络下载图片,如果下载的图片不在缓存中则放入缓存中
                   private ImageView mImageView;
                   private String mURL;
                   public MyAsynctask(String url){
                       mURL=url;
                   }
                @Override
                protected Bitmap doInBackground(String... strings) {
                    String url=strings[0];
                    //从网络获取图片
                    Bitmap bitmap = null;
                    try {
                        bitmap = getbitmapstream(url);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    //将不在缓存的图片加入缓存
                    if (bitmap!=null){
                        addBitMapToCache(url,bitmap);
                    }
                    return bitmap;
                }
    
                @Override
                protected void onPostExecute(Bitmap bitmap) {
                    super.onPostExecute(bitmap);
                    ImageView imageView= (ImageView) mListView.findViewWithTag(mURL);
                    if (bitmap!=null&&imageView!=null){
                        imageView.setImageBitmap(bitmap);
                    }
                    mTask.remove(this);
                    }
                }
            }

    在ImageHolder中设置BaseAdapter中所要获取的方法,设置Lru,若所要获取的图片已经存在则从缓存中获取,若没有在缓存中则需要从从网络中下载(也就是通过自定义方法通过url下载),通过传递进来的屏幕中的第一个和最后一个的item位置,通过for循环,为每一个item设置图片,如果已经存在则从缓存中取出,在找所要定义的imageview的时候,通过已经提前为imageview设置好的tag也就是对应的url找到

    public class Myadapter extends BaseAdapter implements AbsListView.OnScrollListener {
        private Context mContext;
        private List<Newsbeans> mlist;
        private ListView mListView;
        private LayoutInflater mlayoutinflater;
        private boolean mFirstIntial;
        //如果使用new ImageViewHolder方法创建则每次调用都会创建一个新的LRUCache,通过定义全局变量确保只有一个LRUCACHE创建
        public ImageviewHolder mImageViewHolder;
        private int mStart,mEnd;
        public static String mURLs[];
        public Myadapter(Context context, List<Newsbeans> mlist1,ListView listView){
            mlist=mlist1;
            mListView=listView;
            mFirstIntial=true;
            //初始化字符数组的大小
            mURLs=new String[mlist.size()];
            //获取管理器
            mlayoutinflater=LayoutInflater.from(context);
            mImageViewHolder=new ImageviewHolder(mListView);
            mListView.setOnScrollListener(this);
            for (int i=0;i<mlist1.size();i++){
                 mURLs[i]=mlist.get(i).newspic;
            }
        }
    
    
        @Override
        public int getCount() {
    
            return mlist.size();
        }
    
        @Override
        public Object getItem(int i) {
            return mlist.get(i);
        }
    
        @Override
        public long getItemId(int i) {
            return i;
        }
    
        @Override
        public View getView(int i, View convertview, ViewGroup viewGroup) {
            Viewholder viewholder=null;
            if(convertview==null){
                viewholder=new Viewholder();
                //将item的layout文件转化为view,必须是item文件在之后的view中还要找到对应的控件
                convertview=mlayoutinflater.inflate(R.layout.item,null);
                viewholder.contenttext= (TextView)convertview.findViewById(R.id.tv_content);
                viewholder.imageView=(ImageView)convertview.findViewById(R.id.imageview);
                viewholder.titletext=(TextView)convertview.findViewById(R.id.tv_title);
                convertview.setTag(viewholder);
            }
                else {
                viewholder=(Viewholder)convertview.getTag();
            }
                Newsbeans newsbeans=mlist.get(i);
                viewholder.imageView.setImageResource(R.mipmap.ic_launcher);
                //调用方法传递所需信息
                mImageViewHolder.showImageBy(viewholder.imageView,mlist.get(i).newspic);
                viewholder.imageView.setTag(mlist.get(i).newspic);
                viewholder.titletext.setText(newsbeans.newstitle);
                viewholder.contenttext.setText(newsbeans.newscontent);
            return convertview;
        }
    
        @Override
        public void onScrollStateChanged(AbsListView absListView, int i) {
            if(i==SCROLL_STATE_IDLE){
                //如果listview不在滑动状态
                mImageViewHolder.imageLoder(mStart,mEnd);
            }else{
                //如果listview在滑动状态
                mImageViewHolder.cancelTask();
            }
        }
    
        @Override
        public void onScroll(AbsListView absListView, int i, int i1, int i2) {
                mStart=i;
                mEnd=i+i1;
            /*
            * i为firstvisbieitem,i1为visbileItemCount,i2为totalitemcount
            * 在这里判断是否为第一次加载和listview是否开始加载,若没开始加载的时候可见项(visbleitem为0)
            *
            * */
            if (mFirstIntial&&i1>0){
                  mImageViewHolder.imageLoder(mStart,mEnd);
                  mFirstIntial=false;
            }
    
        }
    
        class Viewholder{
            public TextView titletext;
            public TextView contenttext;
            public ImageView imageView;
        }
    }

    通过设置BaseAdapter的onScrollListener接口,在OnScrollChanged方法中设定在只有在滑动后停止的时候才加载所需要的图片,若没有滑动的时候取消所有加载

  • 相关阅读:
    wsl 如何去掉 windows 的环境变量
    wget出现Unable to establish SSL connection
    openssh 升级
    element/JS文件上传和下载excel问题
    mysql操作过程中常见问题汇总
    [VB.NET Tips]线程传递参数四种方法
    主路由拨号_openwrt做旁路由_ipv4端口映射的设置
    Openwrt_Linux_crontab任务_顺序执行脚本
    Armbian_笔记
    Debian10_Centos8_fail2ban
  • 原文地址:https://www.cnblogs.com/edwardru/p/5972797.html
Copyright © 2011-2022 走看看