1.picasso简介

picasso是一实现图片异步加载的第三方库。

Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:

(1).在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。

(2).使用复杂的图片压缩转换来尽可能的减少内存消耗

(3).自带内存和硬盘二级缓存功能

2.使用方式

官方地址:http://square.github.io/picasso/

下载地址:https://github.com/square/picasso

使用Android studio进行开发,所以比较简单,只要引用compile 'com.squareup.picasso:picasso:2.5.2'即可

(1)加载本地图片

Picasso.with(this).load("file:///sdcard/Download/ddd.jpg").resize(100,100).rotate(180,0,0).into(mivPic);

(2)加载网络图片

       load(mstrNetUrl).//networkPolicy(NetworkPolicy.NO_CACHE,NetworkPolicy.NO_STORE).memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE).into(mivPic);

(3)设置占位图片

  Picasso.with(context).load(url).placeholder(R.drawable.user_placeholder).error(R.drawable.user_placeholder_error).into(imageView);

整个库分为 Dispatcher,RequestHandler 及 Downloader,PicassoDrawable 等模块。

Dispatcher 负责分发和处理 Action,包括提交、暂停、继续、取消、网络状态变化、重试等等。

简单的讲就是 Picasso 收到加载及显示图片的任务,创建 Request 并将它交给 Dispatcher,Dispatcher 分发任务到具体 RequestHandler,任务通过 MemoryCache 及 Handler(数据获取接口) 获取图片,图片获取成功后通过 PicassoDrawable 显示到 Target 中。

需要注意的是上面 Data 的 File system 部分,Picasso 没有自定义本地缓存的接口,默认使用 http 的本地缓存,API 9 以上使用 okhttp,以下使用 Urlconnection,所以如果需要自定义本地缓存就需要重定义 Downloader

3.使用内存优化

(1)图片剪裁

在列表页尽量使用裁剪后的图片,在查看大图模式下才加载完整的图片

Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(250),dp2px(250))
.centerCrop()
.into(imageView);

(2)查看大图放弃memory cache

Picasso默认会使用设备的15%的内存作为内存图片缓存,且现有的api无法清空内存缓存。我们可以在查看大图时放弃使用内存缓存,图片从网络下载完成后会缓存到磁盘中,加载会从磁盘中加载,这样可以加速内存的回收。

Picasso.with(getApplication())
.load(mURL)
.memoryPolicy(NO_CACHE, NO_STORE)
.into(imageView);

其中memoryPolicy的NO_CACHE是指图片加载时放弃在内存缓存中查找,NO_STORE是指图片加载完不缓存在内存中。

(3).RecycleableImageView

重写ImageView的onDetachedFromWindow方法,在它从屏幕中消失时回调,去掉drawable引用,能加快内存的回收。

public class RecyclerImageView extends ImageView
{ ...@Override    protected void onDetachedFromWindow() {super.onDetachedFromWindow();setImageDrawable(null);   }
}

可以看到使用了RecyclableImageView的实验在切换过程中产生的内存谷值明显优于ImageView,说明drawable更容易被回收。

(4).新进程中查看大图:

列表页的内存已经非常稳定,但是查看大图时,大图往往占用了20+m内存,加上现有进程中的内存,非常容易oom,在新进程中打开Activity成为比较取巧的避免oom的方式。

<activity android:name=".DetailActivity" android:process=":picture"/>

只要在AndroidManifest.xml中定义Activity时加入process属性,即可在新进程中打开此Activity。由此,picasso也将在新进程中创建基于新ApplicationContext的单例。

(5).列表页滑动优化

Object tag = new Object();
Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(250),dp2px(250))
.centerCrop()
.tag(tag)
.into(imageView);

例如在RecyclerView滑动时监听,处理不同的表现:

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState){if (newState == RecyclerView.SCROLL_STATE_IDLE){Picasso.with(context).resumeTag(tag);}else{Picasso.with(context).pauseTag(tag);}}
});

(6).RGB-565

对于不透明的图片可以使用RGB_565来优化内存。

默认情况下,Android使用ARGB_8888

Android中有四种,分别是:
ALPHA_8:每个像素占用1byte内存
ARGB_4444:每个像素占用2byte内存
ARGB_8888:每个像素占用4byte内存
RGB_565:每个像素占用2byte内存

RGB_565呈现结果与ARGB_8888接近,内存对比如下图

4.demo示例

效果图:

(1)先在app/build.gradle文件添加插件的依赖

    dependencies {  compile fileTree(dir: 'libs', include: ['*.jar'])  compile 'com.android.support:appcompat-v7:23.1.1'  compile 'com.squareup.picasso:picasso:2.5.2'       //这个就是  }  

activity_main.xml主页面布局:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  tools:context=".MainActivity"  android:orientation="vertical">  <ScrollView  android:layout_width="match_parent"  android:layout_height="match_parent">  <LinearLayout  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:orientation="vertical">  <Button  android:id="@+id/btn_listView"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:gravity="center"  android:text="ListView显示图片"/>  <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="下图是根据ImageView大小,显示图片"/>  <ImageView  android:id="@+id/img_one"  android:layout_width="150dp"  android:layout_height="200dp" />  <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="下图是通过程序代码,来显示图片大小"/>  <ImageView  android:id="@+id/img_two"  android:layout_width="150dp"  android:layout_height="100dp" />  <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="加载本地的图片"/>  <ImageView  android:id="@+id/img_three"  android:layout_width="50dp"  android:layout_height="50dp" />  <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="截取图片"/>  <ImageView  android:id="@+id/img_four"  android:layout_width="150dp"  android:layout_height="150dp" />  </LinearLayout>  </ScrollView>  </LinearLayout>  

MainActivity.java主页程序:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;  import com.example.cg.picassolearn.untils.CropSquareTransformation;
import com.squareup.picasso.Picasso;  public class MainActivity extends AppCompatActivity implements View.OnClickListener {  private ImageView img_one;  private ImageView img_two;  private ImageView img_three;  private ImageView img_four;  private Button btn_listView;  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  initControls();  initData();  }  /** * 初始化控件 */  private void initControls() {  img_one = (ImageView)this.findViewById(R.id.img_one);  img_two = (ImageView)this.findViewById(R.id.img_two);  img_three = (ImageView)this.findViewById(R.id.img_three);  img_four = (ImageView)this.findViewById(R.id.img_four);  btn_listView = (Button)findViewById(R.id.btn_listView);  btn_listView.setOnClickListener(this);  }  /** * 加载数据 */  private void initData()  {  /** * 根据ImageView大小,显示图片 * .fit()                                  说明:控件不能设置成wrap_content,也就是必须有大小才行,fit()才让图片的宽高等于控件的宽高,设置fit(),不能再调用resize() * .placeholder(R.drawable.topic_tom)      说明:当图片没有加载上的时候,显示的图片 * .error(R.drawable.topic_sky)            说明:当图片加载错误的时候,显示图片 * .into(img_one)                          说明:将图片加载到哪个控件中 */  Picasso.with(this).load("http://g.hiphotos.baidu.com/image/pic/item/c9fcc3cec3fdfc03e426845ed03f8794a5c226fd.jpg")  .fit()  .placeholder(R.drawable.topic_tom)  .error(R.drawable.topic_sky)  .into(img_one);  /** * 通过程序代码,来显示图片大小 *.resize(200, 150)                        说明:为图片重新定义大小 *.centerCrop()                            说明:图片要填充整个控件,去两边留中间 */  Picasso.with(this).load("http://d.hiphotos.baidu.com/image/h%3D200/sign=745574b6a2ec08fa390014a769ee3d4d/cb8065380cd79123148b447daf345982b2b78054.jpg")  .resize(200, 150)  .centerCrop()  .placeholder(R.drawable.topic_tom)  .error(R.drawable.topic_sky)  .into(img_two);  /** * 加载本地数据库,图片的大小,取消于控件设置的大小 */  Picasso.with(this).load(R.drawable.topic_tom)  .into(img_three);  /** * 截取图片 * .transform(new CropSquareTransformation())        说明:通过程序截取图片 */  Picasso.with(this).load("http://g.hiphotos.baidu.com/image/pic/item/6c224f4a20a446230761b9b79c22720e0df3d7bf.jpg")  .transform(new CropSquareTransformation())  .placeholder(R.drawable.topic_tom)  .error(R.drawable.topic_sky)  .into(img_four);  }  @Override  public void onClick(View v) {  switch (v.getId())  {  case R.id.btn_listView:  ListViewActivity.ListViewStar(this);  break;  }  }
}  

在截取图片的地方,需要自己编写代码: CropSquareTransformation.java

import android.graphics.Bitmap;  import com.squareup.picasso.Transformation;  /** * picasso的Transformation方法,对图片进行截取 * Created by cg on 2016/2/1. */
public class CropSquareTransformation implements Transformation {  //截取从宽度和高度最小作为bitmap的宽度和高度  @Override  public Bitmap transform(Bitmap source) {  int size=Math.min(source.getWidth(),source.getHeight());  int x=(source.getWidth()-size)/2;  int y=(source.getHeight()-size)/2;  Bitmap result=Bitmap.createBitmap(source,x,y,size,size);  if (result!=source){  source.recycle();//释放bitmap  }  return result;  }  @Override  public String key() {  return "square()";  }
}  

在程序中最常用到图片显示可能就是ListView中的应用了,下面我们来看一下,它在listView中的使用。也是相应简单,同样的一行代码。

首先,我们要先建立一个bean,里面放一个图片地址,标题,内容。为了给listVIew加值

News.java

public class News {  private String title;  private String contents;  private String PicUrl;  public News() {  }  public News(String title, String contents, String picUrl) {  this.title = title;  this.contents = contents;  PicUrl = picUrl;  }  public String getTitle() {  return title;  }  public void setTitle(String title) {  this.title = title;  }  public String getContents() {  return contents;  }  public void setContents(String contents) {  this.contents = contents;  }  public String getPicUrl() {  return PicUrl;  }  public void setPicUrl(String picUrl) {  PicUrl = picUrl;  }
}  

为ListView的Item添加布局

lv_item.xml:

    <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="horizontal">  <LinearLayout  android:layout_width="0dp"  android:layout_height="110dp"  android:layout_weight="1"  android:gravity="center">  <ImageView  android:id="@+id/item_pic"  android:layout_width="100dp"  android:layout_height="100dp" />  </LinearLayout>  <LinearLayout  android:layout_width="0dp"  android:layout_height="110dp"  android:layout_weight="3"  android:orientation="vertical">  <TextView  android:id="@+id/txt_title"  android:layout_width="match_parent"  android:layout_height="0dp"  android:layout_weight="1"/>  <TextView  android:id="@+id/txt_content"  android:layout_width="match_parent"  android:layout_height="0dp"  android:layout_weight="2"/>  </LinearLayout>  </LinearLayout>  

lv_Adapter.java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;  import com.example.cg.picassolearn.bean.News;
import com.squareup.picasso.Picasso;  import java.util.List;  /** * ListView的Adapter * Created by cg on 2016/2/1. */
public class lv_Adapter extends BaseAdapter{  private List<News> list_new;  private LayoutInflater inflater;  private Context context;  public lv_Adapter(List<News> list_new, Context context) {  this.list_new = list_new;  this.context = context;  this.inflater = LayoutInflater.from(context);  }  @Override  public int getCount() {  return list_new.size();  }  @Override  public Object getItem(int position) {  return list_new.get(position);  }  @Override  public long getItemId(int position) {  return position;  }  @Override  public View getView(int position, View convertView, ViewGroup parent) {  ItemNews in;  if(convertView==null)  {  in = new ItemNews();  convertView = inflater.inflate(R.layout.lv_item,null);  in.title = (TextView)convertView.findViewById(R.id.txt_title);  in.contents = (TextView)convertView.findViewById(R.id.txt_content);  in.pic = (ImageView)convertView.findViewById(R.id.item_pic);  convertView.setTag(in);  }else  {  in = (ItemNews)convertView.getTag();  }  in.contents.setText(list_new.get(position).getContents());  in.title.setText(list_new.get(position).getTitle());  //注意这里,一行代码,就把图片加载上去了,而且你上下滚动listView你会发现什么,这个大家自己去体会  Picasso.with(context).load(list_new.get(position).getPicUrl()).fit()  .placeholder(R.drawable.topic_tom)  .error(R.drawable.topic_sky)  .into(in.pic);  return convertView;  }  class ItemNews  {  TextView title;  ImageView pic;  TextView contents;  }
}  

ListViewActivity.java

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;  import com.example.cg.picassolearn.bean.News;  import java.util.ArrayList;
import java.util.List;  public class ListViewActivity extends AppCompatActivity {  private ListView lv_main;  private List<News> list_new;  private lv_Adapter lAdapter;  public static void ListViewStar(Context context)  {  Intent intent = new Intent(context,ListViewActivity.class);  context.startActivity(intent);  }  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_list_view);  initControls();  initData();  }  /** * 初始化控件 */  private void initControls() {  lv_main = (ListView)findViewById(R.id.lv_main);  list_new = new ArrayList<>();  lAdapter = new lv_Adapter(list_new,this);  lv_main.setAdapter(lAdapter);  }  /** * 初始化数据 */  private void initData()  {  News news = new News();  news.setTitle("清纯的美女");  news.setContents("我不说什么,大家自己看");  news.setPicUrl("http://g.hiphotos.baidu.com/image/pic/item/6c224f4a20a446230761b9b79c22720e0df3d7bf.jpg");  list_new.add(news);  News news2 = new News();  news2.setTitle("好看的美女");  news2.setContents("我不说什么,大家自己看");  news2.setPicUrl("http://f.hiphotos.baidu.com/image/pic/item/11385343fbf2b211eee0554ac88065380dd78eec.jpg");  list_new.add(news2);  News news1 = new News();  news1.setTitle("狂野的美女");  news1.setContents("我不说什么,大家自己看");  news1.setPicUrl("http://a.hiphotos.baidu.com/image/h%3D200/sign=623f372f0b24ab18ff16e63705fbe69a/267f9e2f070828382f690e1dba99a9014c08f157.jpg");  list_new.add(news1);  News news4 = new News();  news4.setTitle("小护士");  news4.setContents("我不说什么,大家自己看");  news4.setPicUrl("http://f.hiphotos.baidu.com/image/pic/item/738b4710b912c8fc6684dceaf9039245d68821a5.jpg");  list_new.add(news4);  News news5 = new News();  news5.setTitle("古典的美女");  news5.setContents("我不说什么,大家自己看");  news5.setPicUrl("http://c.hiphotos.baidu.com/image/pic/item/342ac65c10385343498219169613b07eca8088bc.jpg");  list_new.add(news5);  News news6 = new News();  news6.setTitle("清纯的美女");  news6.setContents("我不说什么,大家自己看");  news6.setPicUrl("http://c.hiphotos.baidu.com/image/pic/item/a044ad345982b2b7a2f0f7cd33adcbef76099b48.jpg");  list_new.add(news6);  News news7 = new News();  news7.setTitle("清纯的美女");  news7.setContents("我不说什么,大家自己看");  news7.setPicUrl("http://e.hiphotos.baidu.com/image/pic/item/8b13632762d0f7031db73fdc0afa513d2697c5ad.jpg");  list_new.add(news7);  News news8 = new News();  news8.setTitle("清纯的美女");  news8.setContents("我不说什么,大家自己看");  news8.setPicUrl("http://b.hiphotos.baidu.com/image/pic/item/9825bc315c6034a857770337ce134954082376ea.jpg");  list_new.add(news8);  lAdapter.notifyDataSetChanged();  }  }  

对应的布局:

activity_list_view.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"  android:layout_height="match_parent"  tools:context="com.example.cg.picassolearn.ListViewActivity">  <ListView  android:id="@+id/lv_main"  android:layout_width="match_parent"  android:layout_height="match_parent"></ListView>  </RelativeLayout>  

picasso介绍及使用相关推荐

  1. Android 三大图片加载框架的对比——ImageLoader,Picasso,Glide

    一.ImageLaoder介绍 << Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用 多线程下载图片,图片可以来源于网络,文件系统,项目文件夹ass ...

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

    网路下载图片,并以滚动列表的方式展示图片资源,是一种典型的Android App开发场景,但是如何更好的去实现这种效果一直是Android程序员所头疼的事情.比如,将下载的图片数据存储到本地,那就会造 ...

  3. Google推荐的图片加载库Glide介绍(与Picasso比较)

    在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官 ...

  4. 介绍一下Gilde和Picasso以及它们的区别

    Grild 要使用它首先我们需要导依赖  compile 'com.github.bumptech.glide:glide:4.1.1' Glide加载图片 //加载默认图片 Glide.with(t ...

  5. 【转载】一行代码加载网络图片到ImageView——Android Picasso

    原文链接:一句代码加载网络图片到ImageView--Android Picasso  注意:此处使用下面代码需要先配置一下gradle,下载所需包. 具体操作如下图: compile 'com.sq ...

  6. Glide和Picasso的区别

    首先简单的介绍下两个库的出身: Picasso是Square公司出品的一款非常优秀的开源图片加载库 Glide是由Google开发,基于 Picasso,依然有保存了Picasso的简洁风格,但是在此 ...

  7. anroid 图片处理加载对比(image loader,Picasso ,glide,fresco)

    Android 三大图片缓存原理.特性对比 这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事. 从总体设计和原理上对几个图片缓存进行对比,没用到他们 ...

  8. Android开源框架——图片加载与缓存库 Picasso

    介绍 Picasso是由Square开发的一款图片库,具有强大的下载与缓存功能,可以对图片进行处理.它简化了来自外部图片的处理过程,尤其是远程图片. 开源地址:https://github.com/s ...

  9. 剖析Picasso中的内存缓存机制——LruCache

    众所周知,Picasso是一个优秀的Android图片加载库.本篇并不讨论picasso的使用,而是来谈一谈picasso的缓存机制. 我们知道,目前主流的图片解决方案大部分都是三级缓存,即内存缓存. ...

最新文章

  1. 博士学位论文 | 机器阅读理解与文本问答技术研究
  2. WebBrowser内存泄露
  3. SVM-支持向量机(code实现)
  4. 开课吧:分享一下C语言发展史的点点滴滴
  5. 编译JAVA的错误: 编码ascii的不可映射字符
  6. win10熄屏时间不对_浅析win10电脑屏幕熄屏时间设置教程
  7. php移除excel密码,excel保护密码忘记怎么撤销保护工作表
  8. Android数据持久化存储(一)
  9. 小程序源码:全新独立后台修复登录在线答题
  10. Java程序员进阶全过程
  11. 基于51单片机的寻迹小车
  12. 神器:公众号如何从第一篇文章开始看
  13. 【Axure视频教程】中继器表格——下拉列表筛选
  14. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java校园花卉销售系统ef5ox
  15. HPE服务器使用SPP刷新固件方法
  16. 电脑绘画软件哪个好用:试试Artweaver Plus吧,媲美sai绘画软件 | 最新版本的artweaver下载
  17. 2022华为机试4.6第一题舆情热词题解
  18. 条码WMS系统的架构
  19. 【OpenCV】KeyPoint数据结构
  20. Zynq-linux PL与PS通过DMA数据交互

热门文章

  1. 水煮旅途之“天山夜话”
  2. perl mysql 数据推拉_MySQL_Perl操作mysql数据库的方法,Perl对Mysql的操作。 一、标准 - phpStudy...
  3. 记一次失败的导师霸面
  4. Laravel :Illuminate\Encryption\MissingAppKeyException No application encryption key has been specifi
  5. 自定义Linxu启动logo(从其他分区加载logo)
  6. history of program
  7. (三)基于Multisim的电台发射系统:高频功率放大器的设计
  8. 公共WiFi到底该不该连?黑客教父龚蔚这么说
  9. git-bash.exe和git-cmd.exe运行Git的区别
  10. echarts 多条折线图