【Android实习笔记】——图片加载工具Picasso的使用

Picasso介绍

Picasso是Square公司开源的一个Android图形缓存库

A powerful image downloading and caching library for Android 
一个Android下强大的图片下载缓存库

Picasso实现了图片的异步加载,并解决了Android中加载图片时常见的一些问题,它有以下特点:

  • Adapter中取消了不在视图范围内的ImageView的资源加载,因为可能会产生图片错位;
  • 使用复杂的图片转换技术降低内存的使用
  • 自带内存和硬盘的二级缓存机制

为什么要用Picasso

  Android系统作为图片资源加载的主角,它是通过图像的像素点来把图像加载到内存中的;现在一张500W的摄像头拍出的照片(2592x1936),加载到内存中需要大约19M的内存;如果你加入了信号强度不一的网络中进行了复杂的网络请求,并进行图片的缓存与其他处理,你会耗费大量的时间与精力来处理这些问题,但如果用了Picasso, 这些问题都一消而散;

将Picasso加入到你的项目中

 目前Picasso的最新版本是2.5.2,你可以下载对应的Jar包,将Jar包添加到你的项目中,或者在build.gradle配置文件中加入

compile 'com.squareup.picasso:picasso:2.5.2'

注意如果你开启了混淆,你需要将以下代码添加到混淆规则文件中:

-dontwarn com.squareup.okhttp.**

小试牛刀:从网络加载一张图片

Picasso使用简单易用的接口,并有一个实现类Picasso,一个完整的功能请求至少需要三个参数;

  • with(Context context) - Context上下文在很多Android Api中都是必须的
  • load(String imageUrl) - 图片网络加载地址
  • into(ImageView targetImageView) - 想进行图片展示的ImageView

简单用例:

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);

String internetUrl = "http://www.jycoder.com/json/Image/1.jpg";


Picasso

.with(context)

.load(internetUrl)

.into(targetImageView);

  就是这么简单,如果你的 URL地址正确并且图片存在,在几秒中之内就能看到这张图片了;如果图片资源不存在,Picasso也会有错误的回调,现在你已经看到了只需3行代码就能加载图片了,当然这只是冰山一角,让我们继续揭开Picasso的神秘面纱;

图片的其他加载方式

  Picasso的图片不仅仅能加载网络资源,也能从本地文件,Android项目资源,以及URI地址进行图片加载,下面我们就对这三种方式进行实例说明;

从Android Resources 中加载

  代码也是三行,只需要将网络资源地址更改为一个int值地址即可,上代码:

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);

int resourceId = R.mipmap.ic_launcher;


Picasso

.with(context)

.load(resourceId)

.into(targetImageView);

注意: R.mipmapAndroid Studio中新的资源引用路径,这个老司机都知道.

从本地File文件中加载

  如果你让用户选择本地的一张图片进行展示的话,就需要用到这个加载方式了,当然,也是So Easy,只需要将地址更换为一个File即可,上代码:

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);

File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Running.jpg");


Picasso

.with(context)

.load(file)

.into(targetImageView);

注意:这个file并不一定非得是在你的设备中,可以是任意的路径,只要是File路径即可;

URI地址中加载

  这个请求方式相比其他也并没有什么不同,上代码:

public static final String ANDROID_RESOURCE = "android.resource://";

public static final String FOREWARD_SLASH = "/";


private static Uri resourceIdToUri(Context context, int resourceId) {

return Uri.parse(ANDROID_RESOURCE + context.getPackageName() + FOREWARD_SLASH + resourceId);

}


Uri uri = resourceIdToUri(context, R.mipmap.future_studio_launcher);

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);


Picasso

.with(context)

.load(uri)

.into(targetImageView);

注意:为了示范,只能用资源文件转换为URI,并不仅仅是这种方式, 它可以支持任意的URI地址;

前面我们已经介绍了Picasso的基本用法及如何将一张图片加载到ImageView中,下面我们就利用Picasso在ListView中加载图片。

一个ListView的简单应用示例

1: 首先,需要先准备好一些网络图片资源

public static String[] imgUrls = {
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg",
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg",
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg",
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg",
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg",
            "http://pic.616pic.com/ys_b_img/00/66/73/9KnqqgZBFe.jpg"
    };
//这里使用同一张图片

2: 然后写一个简单的Activity,需要一个Adapter,并将Adapter设置到ListView中填充数据

public class PicassoActivity extends AppCompatActivity {

    ListView lv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_picasso);
        lv = (ListView)findViewById(R.id.list_picasso);
        lv.setAdapter(new ImageListAdapter(PicassoActivity.this, imgUrls));
    }
}

3:我们需要在Adapter中加载一个ListView子item的layout文件名为item_picasso.xml,同时修改activity_picasso.xml中的布局

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="300dp">
</ImageView>
<LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/list_picasso"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
</LinearLayout>

4: 我们还需要一个自定义的Adapter,功能很简单,只显示一张图片即可

public class ImageListAdapter extends ArrayAdapter {
    private Context context;
    private String[] imageUrls;

    public ImageListAdapter(Context context,String[] imageUrls){
        super(context, R.layout.item_picasso,imageUrls);

        this.context = context;
        this.imageUrls = imageUrls;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView==null){
            convertView = View.inflate(context,R.layout.item_picasso,null);
        }
        Picasso.with(context).setIndicatorsEnabled(true);
        //加载图片
        Picasso
                .with(context)
                .load(imageUrls[position])
                .into((ImageView) convertView);
        return convertView;
    }
}

注意:

  • 我们一般会复用ConvertView来保持listview的快速平滑的滚动,而Picasso的一个优点就是会自动处理划出屏幕外的图片请求,并给对应的ImageView加载出正确的资源;
  • 另外,你会发现当你上下滚动后,会发现图片加载速度有了明显的提升,这正是因为Picasso的高速缓存,而且不需要再去从网络加载,Picasso所实现的缓存的大小取决于你自己的设备;
  • Picasso加载图片的资源会从三个地方进行获取, 内存,磁盘,和网络,这些操作都不需要你自己处理,Picasso已经能智能完成;

如果图片地址不存在或为空怎么处理

上面我们写的代码都是在正常的情况下,但是如果我们的图片地址错误将怎么处理呢,如果不去处理,网络可能会一直请求或者我们的屏幕上会出现一片空白,这都不是我们希望看到的.

Picasso给了我们两种解决方案:

  • 在判断为空的地址时,取消网络请求,调用cancelRequest(),然后调用imageView.setImageDrawable(null)
  • 或者调用Picasso的.placeHolder()方法进行图片的替换展示
  • 如果图片网址错误,我们也可以调用.error()方法进行图片替换
@Override

public View getView(int position, View convertView, ViewGroup parent) {

if (convertView==null){

convertView = View.inflate(context,R.layout.item_picasso,null);

}

ImageView imageView = (ImageView)convertView;

if (TextUtils.isEmpty(imageUrls[position])){

Picasso

.with(context)

.cancelRequest(imageView);

imageView.setImageDrawable(null);

}else {

//加载图片

Picasso

.with(context)

.load(imageUrls[position])

.placeholder(R.mipmap.ic_launcher)

.error(R.mipmap.ic_launcher)

.into((ImageView) convertView);

}

return convertView;

}

注意:.placeholder().error()所传的参数与.load()相同

猜你喜欢

转载自blog.csdn.net/u012198209/article/details/81081392