让你的安卓开发更容易(三)——Picasso

Picasso是Android下一个强大的图片下载和缓存类库,代码借口简洁易懂,功能强大,Picasso有如下特性:

  • 处理Adapter中的ImageView回收和取消已经回收ImageView的下载进程
  • 使用最少的内存完成复杂的图片转换,比如把下载的图片转换为圆角等
  • 自动添加磁盘和内存缓存

下面通过介绍Android原生的图片下载缓存功能和Picasso进行对比,看看使用Picasso有哪些好的地方。

Android原生的图片下载功能

在没有使用Picasso的情况下,如果想做到图片下载以及缓存,需要编写大量代码。

图片下载

Android的图片下载是不能在主线程里面进行的,需要新创建一个线程进行操作。

  • 首先要继承AsyncTask类,Android的一个异步操作类。
DownloadTask.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import com.github.zzm.bushu.app.model.LogTag;

import java.io.*;
import java.net.URL;

public class DownloadTask extends AsyncTask<String, Void, String> {
  private File imageFile;
    private ImageView imageView;

    public DownloadTask(File imageFile, ImageView imageView) {
        this.imageFile = imageFile;
        this.imageView = imageView;
    }
  ...
}
  • 实现doInBackground方法。

该方法接受一个可变String参数,表示可以进行多个url下载,但这url参数是从哪里传进来的呢?

我们后面在使用这个DownloadTask类时,会调用其exexute(String... url)的方法,url参数就是从这里传进去的。

下面的代码中通过new URL(url).openStream()进行图片下载,然后新建一个文件输出流,将图片写到输出文件中。

DownloadTask.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    @Override
    protected String doInBackground(String... urls) {
        storageImage(urls[0]);
        return null;
    }

    private void storageImage(String url) {
        FileOutputStream outputStream;
        try {
            outputStream = new FileOutputStream(imageFile);
            outputStream.write(getImageBytes(url));
            outputStream.close();
        } catch (Exception e) {
            Log.e(LogTag.DownloadTask.name(), "storage image error:" + e.getMessage());
        }
    }

    private byte[] getImageBytes(String url) throws IOException {
        InputStream in = new BufferedInputStream(new URL(url).openStream());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int n;
        while (-1 != (n = in.read(buf))) {
            out.write(buf, 0, n);
        }
        out.close();
        in.close();
        return out.toByteArray();
    }
}
  • 实现onPostExecute方法,这个方法是在图片下载完成后调用的,我们可以将下载的图片指定显示到某个imageView中。
DownloadTask.java
1
2
3
4
    @Override
    protected void onPostExecute(String ignore) {
        imageView.setImageBitmap(BitmapFactory.decodeFile(imageFile.getAbsolutePath()));
    }

图片缓存

我们要自己实现图片缓存的功能也比较简单,代码如下。(但如果已经有Picasso这种强大的类库,我们又何必自己造轮子呢?)

  • 要找到下载的图片文件,我们要自己定义文件的命名规则和存放路径,这样才能方便我们找到文件。
MyAdapter.java
1
2
3
4
5
6
7
    File imageFile = getImageFile(bookName);

    private File getImageFile(String bookName) {
        File imageFile = new File(context.getFilesDir(), bookName + ".png");
        Log.d(LogTag.BooksAdapter.name(), "file path: " + imageFile.getAbsolutePath());
        return imageFile;
    }
  • 判断文件是否存在,如果不存在则进行首次下载,如果已经存在了则直接从磁盘上面加载文件。
MyAdapter.java
1
2
3
4
5
    if (imageFileEmpty(imageFile)) {
            downloadImage(bookName, imageView);
        } else {
            imageView.setImageBitmap(BitmapFactory.decodeFile(imageFile.getAbsolutePath()));
        }
  • 判断是否有网络,有的话进行图片下载,调用刚才介绍的DownloadTask类,然后调用execute的方法即可,这样后台就会异步帮你将图片下载下来,然后进行显示。
MyAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
    private void downloadImage(String bookName, ImageView imageView) {
        if (networkOk()) {
            String url = format("%s%s/%s.png", STORAGE_BASE_URL, getScreenDensity(), bookName);
            Log.d(LogTag.BooksAdapter.name(), format("url: %s", url));
            new DownloadTask(getImageFile(bookName), imageView).execute(url);
        }
    }

    private boolean networkOk() {
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());
    }

Picasso的图片下载功能

看完Android的图片下载功能,发现我们写了不少代码,现在来看看Picasso是怎么实现的。

MyAdapter.java
1
 Picasso.with(getContext()).load(url).into((ImageView) viewImage);

一句话就搞定了,就是这么简单,是不是觉得生活美好了很多。

Picasso会在应用的cache目录下新建一个picasso-cache文件夹,里面就是picasso的图片缓存文件。

相关链接

Comments