
本文记录图片加载功能中不涉及缓存的部分。
数据
先搞了一些数据,都是 pixabay 的免费图。
public static final List<String> IMAGES = Arrays.asList(
"https://cdn.pixabay.com/photo/2017/07/18/18/01/little-girl-2516578_960_720.jpg",
"https://cdn.pixabay.com/photo/2016/04/23/10/43/child-1347385_960_720.jpg",
"https://cdn.pixabay.com/photo/2015/06/02/20/58/little-girl-running-795505_960_720.jpg",
"https://cdn.pixabay.com/photo/2014/10/07/01/38/girl-477015_960_720.jpg",
"https://cdn.pixabay.com/photo/2015/07/27/18/52/water-863053_960_720.jpg",
"https://cdn.pixabay.com/photo/2016/05/12/07/13/kids-1387118_960_720.jpg",
"https://cdn.pixabay.com/photo/2017/06/22/23/40/picking-flowers-2432972_960_720.jpg",
"https://cdn.pixabay.com/photo/2018/01/08/20/24/little-girl-3070211_960_720.jpg",
"https://cdn.pixabay.com/photo/2015/06/25/17/56/baby-821627_960_720.jpg",
"https://cdn.pixabay.com/photo/2017/07/18/18/02/chasing-butterflies-2516581_960_720.jpg",
"https://cdn.pixabay.com/photo/2015/07/31/22/59/princess-869721_960_720.jpg"
);
加载的入口
在 RecyclerViewAdapter 的 bind 方法中启动 AsyncTask。
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
imageView.setTag(url);
ImageWorkTask task = new ImageWorkTask(url);
task.execute();
mTasks.add(task);
}
下载图片
分为两个部分
一是网络请求部分:
@Override
protected Bitmap doInBackground(String... strings) {
HttpURLConnection connection = null;
try {
URL url = new URL(this.url);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(false);
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setUseCaches(false);
connection.setChunkedStreamingMode(0);
connection.setConnectTimeout(3000);
connection.connect();
// 主要是为了获取 InputStream
Bitmap bitmap = getBitmapFromInputStream(connection.getInputStream());
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
二是解析图片部分:
private Bitmap getBitmapFromInputStream(InputStream input) {
Bitmap bitmap = null;
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
// 读取所有数据,不直接 decodeStream,因为可能图片太大。
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) >= 0) {
output.write(buffer, 0, len);
}
byte[] array = output.toByteArray();
// 计算缩放尺寸,这里最好用 R.dimension 不要写死。
int scale = calculateScaleOfImage(array, 240 * 2, 240 * 2);
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = scale;
// 然后解析成 Bitmap
bitmap = BitmapFactory.decodeByteArray(array, 0, array.length, option);
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
private int calculateScaleOfImage(byte[] array, int maxWidth, int maxHeight) {
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(array, 0, array.length, option);
int xScale = Math.round((float) option.outWidth / maxWidth);
int yScale = Math.round((float) option.outHeight / maxHeight);
return Math.max(xScale, yScale);
}
显示出来
这里用的是查找 tag 的策略,好处是不用保存 imageView 的引用。
@Override
protected void onPostExecute(Bitmap bitmap) {
ImageView view = mRecyclerView.findViewWithTag(url);
if (view != null) {
view.setImageBitmap(bitmap);
}
mTasks.remove(url);
}
清理
所有的 ImageWorkTask
在退出界面后应取消掉。
public void clearTasks() {
for (ImageWorkTask task : mTasks) {
task.cancel(true);
}
}
总结
由于 RecyclerView 复用 ItemView 的原因,滑动到被复用的 ItemView 并不会立刻显示出正确的图片,还是显示原来的图片,得等网络下载完毕后才能显示正确。不用缓存真的是体验很差。
(ole)
网友评论