至少作為基本的 Loader 而言, 我認為 Picasso 好用多了.
環境:
SDK: android-17
IDE: android-studio
Device: Moto Atrix with 4.2.2
External Libraries: picasso
本篇跟之前一樣, 使用簡單的 gridview 當作 main layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <GridView android:id="@+id/gridview" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawSelectorOnTop="true" android:alwaysDrawnWithCache="false" android:fadeScrollbars="true" android:cacheColorHint="@android:color/transparent" android:numColumns="3" android:columnWidth="160dp"/> </RelativeLayout>
gridview row 的 layout 跟之前稍微有點不一樣.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageview" android:layout_width="160dp" android:layout_height="240dp" android:layout_centerInParent="true" android:scaleType="centerInside" android:contentDescription="@null"/> </RelativeLayout>
這邊我並不使用 Picasso 內建的 loader, 而是根據自己的需求實作.
此範例中我只是很簡單的實作 Disk Cache 的機制.
MyURLConnectionLoader.java
package tw.clotai.picassoexample; import android.content.Context; import android.net.Uri; import android.os.Environment; import android.util.Log; import com.squareup.picasso.Loader; import java.io.*; import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * A {@link com.squareup.picasso.Loader} which uses {@link java.net.HttpURLConnection} to chapter_main images. A disk cache of 10MB * will automatically be installed in the application's cache directory, when available. */ public class MyURLConnectionLoader implements Loader { private static final String HASH_ALGORITHM = "MD5"; private static final int RADIX = 10 + 26; private final Context context; public MyURLConnectionLoader(Context context) { this.context = context.getApplicationContext(); } protected HttpURLConnection openConnection(String path) throws IOException { return (HttpURLConnection) new URL(path).openConnection(); } @Override public Response load(Uri uri, boolean b) throws IOException { Response res = null; String cacahePath = PicassoHelper.getCachePath(context); if (cacahePath == null) { return res; } String url = uri.toString(); if (url == null) { return res; } String key = generateUniqueID(url); if (key == null) { return res; } if (!url.startsWith("http")) { File f = new File(url); if (f.exists()) { FileInputStream fin = new FileInputStream(f); res = new Response(fin, true); } return res; } File f = new File(cacahePath, key); if (f.exists()) { FileInputStream fin = new FileInputStream(f); res = new Response(fin, true); } else { InputStream in = null; try { HttpURLConnection connection = openConnection(url); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11"); connection.setRequestProperty("Accept-Language", "en-US,en;q=0.8"); connection.setUseCaches(true); connection.setDoInput(true); connection.setConnectTimeout(30000); connection.setReadTimeout(30000); connection.setRequestMethod("GET"); connection.connect(); in = connection.getInputStream(); copyToFile(in, f); } finally { if (in != null) { in.close(); } } if (f.exists()) { FileInputStream fin = new FileInputStream(f); res = new Response(fin, false); } } return res; } private String generateUniqueID(String url) { StringBuilder sb = new StringBuilder(); byte[] md5; BigInteger bi = null; try { MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); digest.update(url.getBytes()); md5 = digest.digest(); bi = new BigInteger(md5).abs(); } catch (NoSuchAlgorithmException e) { } if (bi == null) { return null; } sb.append(bi.toString(RADIX)); return sb.toString(); } private void copyToFile(InputStream in, File dest) throws IOException { FileOutputStream fos = null; BufferedInputStream bin = null; BufferedOutputStream bout = null; try { fos = new FileOutputStream(dest); bin = new BufferedInputStream(in, 8192); bout = new BufferedOutputStream(fos, 8192); byte[] rdata = new byte[8192]; int count = 0; while ((count = bin.read(rdata)) != -1) { bout.write(rdata, 0, count); } bout.flush(); } finally { if (bin != null) { bin.close(); } if (fos != null) { if (fos.getFD() != null) { fos.getFD().sync(); } } if (bout != null) { bout.close(); } if (fos != null) { fos.close(); } } } }
另外為了方便使用, 建立一個 singleton PicassoHelper.
以下為部份內容
public static PicassoHelper getInstance(Context c) { if (helper == null) { if (c == null) { return null; } synchronized (PicassoHelper.class) { if (helper == null) { helper = new PicassoHelper(c); } } } return helper; } private PicassoHelper(Context c) { mContext = c.getApplicationContext(); Picasso.Builder builder = new Picasso.Builder(c); builder.loader(new MyURLConnectionLoader(c)); mPicasso = builder.build(); mPicasso.setDebugging(false); PicassoHelper.getCachePath(mContext); } public void load(String url, ImageView v) { v.setImageResource(R.drawable.ic_launcher); if (url == null) { return; } mPicasso.load(url) .resize(160, 240) .error(R.drawable.ic_launcher) .centerCrop() .into(v); }
這樣大致上完成了.
同樣使用上次的範例, 執行結果如下:
原始碼下載:
PicassoExampleProject.zip
參考資料:
#1 Picasso v1.1.1
沒有留言:
張貼留言