原生代码加载网络图片和Volley和Picasso的简单介绍和优缺点对比

网路下载图片,并以滚动列表的方式展示图片资源,是一种典型的Android App开发场景,但是如何更好的去实现这种效果一直是Android程序员所头疼的事情。比如,将下载的图片数据存储到本地,那就会造成一个原声Android代码的卡顿(IO流的操作会造成裂变滚动的卡顿)。如果将他们存储在网络断,那程序员又必须去关心何时要取消请求队列中的请求,如何将下载的图片数据在内存中做高效的缓存,以及一系列的问题。

偏偏在这时,谷歌I/O大会上介绍了两个有意思的图片加载库:Volley和Picasso。 其实本质上这两个库的功能并不是一样的,但是它们都提供了解决图片加载问题的方案。我决定将她俩都部署到我的项目当中PhotoGallery,并看看她俩各自优势。

PhotoGallery是一个Flickr的前端应用,显示最新的Flickr图片,先看下PhotoGallery的截图:


如果继续往下拉,会看到更多的图片,接下来让我们关注在图片加载问题上。

在PhotoGalleryFragment碎片中,有一个叫做ThumbnailDownloader的组件,它是一个单线程,专门用来负责下载图片,并且提供了一个回调接口用来通知下载完成。

ThumbnailDownloader在Activity的onCreate方法中进行初始化,主要分三步:

1、设置回调监听

2、启动线程

3、启动循环,保证请求队列已经准备好接受一个一个的图片加载请求

具体代码参考如下:

 @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);...mThumbnailThread = new ThumbnailDownloader<ImageView>(new Handler());mThumbnailThread.setListener(new ThumbnailDownloader.Listener<ImageView>() {public void onThumbnailDownloaded(ImageView imageView, Bitmap thumbnail) {if (isVisible()) {imageView.setImageBitmap(thumbnail);}}});mThumbnailThread.start();mThumbnailThread.getLooper();}

这里的listener就是负责当图片下载完毕之后,将其设置到ImageView控件之上

当调用onDestroyView方法时,过时的请求需要被清空掉:

@Overridepublic void onDestroyView() {super.onDestroyView();mThumbnailThread.clearQueue();}

然后在onDestroy方法中,整个线程需要停止:

@Overridepublic void onDestroy() {super.onDestroy();mThumbnailThread.quit();}

在PhotoGallery的适配器中,先给ImageView设置一个默认的本地图片,然后调用ThumbnailDownloader的queueThumbnail方法,向队列中添加图片加载请求:

private class GalleryItemAdapter extends ArrayAdapter<GalleryItem> {public GalleryItemAdapter(ArrayList<GalleryItem> items) {super(getActivity(), 0, items);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = getActivity().getLayoutInflater().inflate(R.layout.gallery_item, parent, false);}GalleryItem item = getItem(position);ImageView imageView = (ImageView)convertView.findViewById(R.id.gallery_item_imageView);imageView.setImageResource(R.drawable.brian_up_close);mThumbnailThread.queueThumbnail(imageView, item.getUrl());return convertView;}}

Okay! 到这里原生的写法差不多已经完成了,ThumbnailDownloader是一个非常简单的图片加载组件,它按照请求被添加进队列的次序,依次的下载每一张图片。如果请求已经过时,则会忽略此请求而直接跳转到下一个请求。这种原生的实现有如下几个优点:简单,体积小,容易理解。

但是它也有它的缺陷:

我不得不在多个碎片的生命周期方法中做聚合的工作,比如:我必须在分3步来对ThumbnailDownloader做初始化,需要手动的清空过时的请求,当碎片结束后需要将线程停止掉。以上问题可以通过一个单例的模式来解决,但是如果使用单例,问题就会接踵而来:当有多个碎片都需要下载图片时,我的APP需要可以解决多个碎片请求的同步问题,这样就会将问题搞得更严重,通俗来讲,也就是解一个B级Bug,引出3个A级Bug。 OMG!!

妈蛋!我受够了,喝杯果汁先。

先品尝下Picasso, 感觉如丝般顺滑 

Picasso这个框架是由国外的一家叫Square的公司所研发的。在工程中导入这个也是非常的简单,只需在pom文件中添加几行配置,或者是下载相应jar包之后在eclipse中导入即可。Squqre声称Picasso已经考虑并解决了图片加载的异步缓存等问题,具体的使用Picasso加载图片只需一行代码搞定,如下所示:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Square说的没有错,上面这行代码同我最终自己实现的组件非常类似。并且onCreate(),onDestroyView(),onDestroy()方法通通不需要!然后在适配器中只要做一下稍微的修改即可,如下所示:

private class GalleryItemAdapter extends ArrayAdapter<GalleryItem> {public GalleryItemAdapter(ArrayList<GalleryItem> items) {super(getActivity(), 0, items);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = getActivity().getLayoutInflater().inflate(R.layout.gallery_item, parent, false);}GalleryItem item = getItem(position);ImageView imageView = (ImageView)convertView.findViewById(R.id.gallery_item_imageView);imageView.setImageResource(R.drawable.brian_up_close);Picasso.with(getActivity()).load(item.getUrl()).noFade().into(imageView);return convertView;}}

以上就是使用Picasso的整个实现。其实Picasso还具备了指定图片的placeholder的功能,并且它似乎复写了ImageView缩放的功能代码,因此我都是自己写placeholder。另外Picasso在下载完图片进行展示的时候,会有一个渐现的效果。


总结一下,使用Picasso的好处是什么呢?

1、一个自动被创建的图片加载的单例

2、图片可以被自动的缓存在内存或者硬盘当中

3、请求可以随时取消

4、可以同时执行多个加载请求

但是Picasso也有两个问题让我头疼,对于ImageView的scaleType属性,在使用Picasso时,并不会生效。比如如下代码:

Picasso.with(getActivity()).load(item.getUrl()).placeholder(R.drawable.brian_up_close).centerCrop().noFade().into(imageView);

但是听说在最新版本中已经可以支持了。有待验证!

另外Picasso致命的问题就是不能加载大图片,虽然不能导致内存溢出问题,但是去不能正常下载图片并显示


接下来看一下Volley,Volley其实并不是一个图片的加载库--它是一个轻量的网络请求库,核心部分就是处理网络请求并缓存请求结果。简单使用如下代码所示:

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mQueue = Volley.newRequestQueue(getActivity());GalleryItemRequest itemsRequest = GalleryItemRequest.newRecentItemsRequest(null, new Listener<ArrayList<GalleryItem>>() {@Overridepublic void onResponse(ArrayList<GalleryItem> items) {mItems = items;setupAdapter();}});itemsRequest.setTag(this);mQueue.add(itemsRequest);}@Overridepublic void onDestroy() {super.onDestroy();mQueue.cancelAll(this);}

GalleryItemRequest是一个自定义的网络请求解析类,用于将请求返回的xml数据填充到一个model类中。

接下来看一下使用Volley如何进行图片的加载:

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);...mQueue = Volley.newRequestQueue(getActivity());mImageLoader = new ImageLoader(mQueue, new ImageCache() {@Overridepublic void putBitmap(String key, Bitmap value) { }@Overridepublic Bitmap getBitmap(String key) {return null;}});...}

注意:在一个实际App中,mQueue和mImageLoader一般是在Application中进行初始化,并在整个app中是以单例的形式存在。

然后是适配器中的代码:

private class GalleryItemAdapter extends ArrayAdapter<GalleryItem> {public GalleryItemAdapter(ArrayList<GalleryItem> items) {super(getActivity(), 0, items);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = getActivity().getLayoutInflater().inflate(R.layout.gallery_item_network, parent, false);}GalleryItem item = getItem(position);NetworkImageView imageView = (NetworkImageView)convertView.findViewById(R.id.gallery_item_imageView);imageView.setDefaultImageResId(R.drawable.brian_up_close);imageView.setImageUrl(item.getUrl(), mImageLoader);return convertView;}}



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22910.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【历史上的今天】10 月 21 日:最短命的流媒体;Imgur 创始人出生;王安申请磁芯存储器专利

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2021 年 10 月 21 日&#xff0c;在 1883 年的今天&#xff0c;伊曼纽尔诺贝尔&#xff08;Noble&#xff09;诞生&#xff0c;以他命名的诺贝尔奖每年会授予世界各国在…

在AWS上部署、监控和扩展机器学习模型

作者|Aparna Dhinakaran 编译|Flin 来源|towardsdatascience 部署健壮的、可扩展的机器学习解决方案仍然是一个非常复杂的过程,需要大量的人力参与,并做出很多努力。因此,新产品和服务需要很长时间才能上市,或者在原型状态下就被放弃,从而降低了行业内的对它的兴趣。那么,…

使用Lambda和S3构建高度可扩展的Imgur克隆

因此&#xff0c;我之前两次尝试在一夜之间成为百万富翁的尝试已经失败了。 当然&#xff0c;我设法鼓起了一点兴奋&#xff0c;但是我还没有法拉利坐在我自己家的车道上…… 这第三次尝试肯定是赢家&#xff0c;对吗&#xff1f; 我将建立一个可以与流行图像托管网站Imgur媲…

php匿名图文贴程序,使用imgur api v3使用php匿名上传图像

我计划使用其api匿名上传图像到imgur,我在匿名上传类别中注册了我的应用程序,并获得客户端ID和客户端密码,如何使用php将图像上传到imgur并将图像直接检索到图像&#xff1f; 任何人都可以建议任何示例的链接&#xff1f; 这是我试图做的,但我得到错误“致命错误&#xff1a;最…

uPic 图床配置教程 - Imgur

uPic 图床配置教程 - Imgur 配置项说明Client ID 获取方式 配置项说明 Client ID: Applications Client ID Client ID 获取方式 1.打开Imgur 官网并登陆 2.进入应用注册页面 3.按要求填写表单信息 4.注意Authorization type选项必须选择OAuth 2 authorization without a cal…

在线图片托管服务imgur

免费的图片分享网站imgur 什么是imgur 网址:https://imgur.com/ Imgur于2009年由俄亥俄大学一位大三学生Alan Schaaf创办&#xff0c;很快就获得了很多人的关注。 Imgur是一个在线图片托管服务网站。网站于2009年2月23日由阿兰沙夫创建。Imgur为用户提供免费图片托管服务&a…

Wallpaper Engine 提取/导出原壁纸

文章目录 前言一、壁纸选取二、提取壁纸总结 前言 本教程基于大佬制作的pkg解压项目&#xff0c;为小白提供的简单教程&#xff0c;项目源地址 https://github.com/notscuffed/repkg 一、壁纸选取 打开 Wallpaper Engine&#xff0c; 选择想要提取的壁纸&#xff0c;右键选择…

微信壁纸小程序V1.2.0(自带后台上传图片)

前篇&#xff1a;微信壁纸头像小程序&#xff08;附源码&#xff09;_热衷与自由的博客-CSDN博客_头像小程序源码 前言 在上篇文章中&#xff0c;我给大家介绍了一个纯前端的微信壁纸小程序&#xff0c;也简单教会大家如何去搭建&#xff0c;但是这个小程序的图片是通过网上开放…

Wallpaper壁纸提取得到tex文件,tex文件转图像,tex文件转png,tex文件提取壁纸,Wallpaper壁纸提取无法得到图像文件,RePKG-GUI提取得到tex文件而不是图像的解决方法

之前我们介绍了如何利用RePKG-GUI工具从Wallpaper壁纸的sence.pkg文件提取壁纸&#xff0c;但最近在提取壁纸时&#xff0c;我发现&#xff0c;有一小部分壁纸无法利用RePKG-GUI工具提取得到图像文件&#xff0c;而是会得到一个.tex类型的文件。 Bug是怎么产生的暂时不知道&am…

一键提取Wallpaper Engine壁纸 pkg格式壁纸图片素材导出教程

wallpaper engineer下载的壁纸文件并不能直接查看&#xff0c;在资源管理器中打开后会有一个scene.pkg的文件中。并不能打开&#xff0c;网上搜了些解决办法&#xff0c;记录一下。 软件下载链接如下&#xff1a; 点我下载 提取码&#xff1a;kwft 下载后直接解压点击RePKG-GU…

(转载)《HelloGitHub》第 82 期

《HelloGitHub》第 82 期 原文链接&#xff1a;HelloGitHub&#xff5c;第 82 期https://hellogithub.com/periodical/volume/82 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目&#xff0c;每月 28 号更新一期。 这里有好玩和入门级的开源项目、开源书籍、实战项目、企业…

23/04/16使用pyecharts绘制中国地图并显示城市

需求 近日几个高中朋友都上岸研究生&#xff0c;某人提议做一个求学路线图&#xff0c;这种技术活儿当然就交给我了。 一共是两幅图&#xff0c;本科城市分布图和研究生城市分布图背景是中国地图在地图中标记大学所在城市在标记点上显示每个人的头像附录显示大学名称每个人本…

ChatGPT中的提示工程(Prompt)怎么做?DAIR.AI最新《提示工程指南》,全面讲述提示技术,附书册课件视频...

来源&#xff1a;专知 提示工程是一门相对较新的学科&#xff0c;用于开发和优化提示&#xff0c;以有效地将语言模型(LM)用于各种应用和研究主题。提示工程技能有助于更好地理解大型语言模型(LLM)的能力和局限性。 研究人员使用prompt engineering来提高LLM在广泛的常见和复杂…

ChatGPT引发混乱!数千种期刊:它不能成为论文作者

本文来源&#xff1a;艾思科蓝整理自财新网、卫报、中国科学报、百度百科&#xff0c;编辑&#xff1a;募格学术 ChatGPT诞生才两个月&#xff0c;但它给全世界投下的「重磅炸弹」就没停下来过。 日前&#xff0c;中国人民大学首都发展与战略研究院副院长郭英剑也发表了题为“2…

【算法动画图解】:安利一款昨天发现的app

偶然看到一个app&#xff1a;算法动画图解&#xff0c;用动画的形式帮你把基础算法捋一遍&#xff0c;个人觉得很赞。 如下是目录。后面有空我会逐个大类更新具体内容。 1、分类 &#xff08;1&#xff09;冒泡排序 &#xff08;2&#xff09;选择性排序 &#xff08;3&…

chatgpt赋能python:如何用Python制作动画?

如何用Python制作动画&#xff1f; Python作为一种优秀的编程语言&#xff0c;可以用于不同领域的编程。其中&#xff0c;Python也可以被用于创建动画。使用Python的主要好处之一是其强大的Matplotlib库&#xff0c;它可以帮助我们更轻松地创建可视化效果。 什么是Matplotlib…

GAN生成漫画脸

最近对对抗生成网络GAN比较感兴趣&#xff0c;相关知识点文章还在编辑中&#xff0c;以下这个是一个练手的小项目~ (在原模型上做了&#xff0c;为了减少计算量让其好训练一些。) 一、导入工具包 import tensorflow as tf from tensorflow.keras import layersimport numpy a…

拥抱毒瘤 DDD!

点击关注公众号&#xff0c;Java干货及时送达&#x1f447; 来源&#xff1a;小姐姐味道 牛B的人物&#xff0c;早已经厌倦了中英文混杂&#xff0c;他们更进一步&#xff0c;使用中英文缩写&#xff0c;对普通人进行降维打击。更厉害的&#xff0c;造就新的名词&#xff0c;并…

技术人的618种草书单,这些好书值得收藏

虽然才刚刚进入 6 月&#xff0c;但各大网店的 618 活动都已经悄悄拉开帷幕&#xff0c;最近图灵君收到读者们的催更&#xff0c;希望我们推荐一些值得购买的书&#xff0c;想趁着 618 期间下手&#xff0c;于是火速响应大家的需求&#xff0c;集结了各方数据&#xff0c;整理出…

人工智能的黎明:从信息动力学的角度看ChatGPT| 观点

David S. Soriano, CC BY-SA 4.0 via Wikimedia Commons 导读&#xff1a; 以ChatGPT为代表的新的人工智能语言模型的出现与更迭&#xff0c;引发人们极大的兴奋和关注。 物理学家祁晓亮从信息动力学的角度分析&#xff0c;认为AI革命的标志是信息处理复杂度的临界点。AI还没有…