如何用Picasso加载布局背景并缓存,及保存View背景Drawable提速
嘿,这两个Android开发的问题我都碰到过,给你详细说说靠谱的解法!
问题1:如何使用Picasso加载布局背景并对其进行缓存?
其实Picasso本身就自带内存+磁盘双缓存,只要用正确的方式加载图片到View背景,缓存就会自动生效,不用额外配置。因为Picasso默认是给ImageView做加载的,要加载到普通View(比如LinearLayout)的背景,我们可以用Target接口来实现:
// 新版Picasso用Picasso.get(),旧版本可替换为Picasso.with(context) Picasso.get() .load("你的图片网络URL") .placeholder(R.drawable.default_background) // 加载中的占位图 .error(R.drawable.error_background) // 加载失败的占位图 .into(new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { // 加载成功后设置为View背景 yourLinearLayout.setBackground(new BitmapDrawable(getResources(), bitmap)); // from参数可判断缓存来源:MEMORY(内存缓存)、DISK(磁盘缓存)、NETWORK(网络下载) // 打印日志就能直观看到缓存是否生效 Log.d("Picasso", "图片从" + from.name() + "加载"); } @Override public void onBitmapFailed(Exception e, Drawable errorDrawable) { yourLinearLayout.setBackground(errorDrawable); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { yourLinearLayout.setBackground(placeHolderDrawable); } });
下次再调用这段代码加载同一个URL时,Picasso会先检查内存缓存,没有的话去磁盘缓存找,都没有才会发起网络请求,完全不用你手动处理缓存逻辑~
问题2:在onSaveInstanceState中保存Drawable,避免重复网络加载
你的需求是Activity重建(比如横竖屏切换)时,不用重新下载图片,直接复用之前的背景。这里有两个方案,推荐优先用第一个:
方案1:直接利用Picasso的缓存(最省心)
因为Picasso已经把图片缓存到本地了,你完全不用手动保存Drawable!只需要在onResume()或者onCreate()里再次调用问题1中的加载代码就行——Picasso会自动从缓存读取,不会发起网络请求,速度快还不会出错。
比如:
@Override protected void onResume() { super.onResume(); // 不管有没有背景,直接调用加载方法,Picasso会自动处理缓存 loadBackgroundWithPicasso(); } // 把加载逻辑抽成单独方法,方便复用 private void loadBackgroundWithPicasso() { Picasso.get() .load("你的图片URL") .placeholder(R.drawable.default_background) .error(R.drawable.error_background) .into(new Target() { // 这里的实现和问题1里一致 @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { yourLinearLayout.setBackground(new BitmapDrawable(getResources(), bitmap)); } @Override public void onBitmapFailed(Exception e, Drawable errorDrawable) { yourLinearLayout.setBackground(errorDrawable); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { yourLinearLayout.setBackground(placeHolderDrawable); } }); }
这样不管Activity怎么重建,只要Picasso的缓存还在,就不会重新下载,完美解决你的需求。
方案2:手动保存Bitmap到Bundle(适合特殊场景)
如果因为某些原因必须手动保存背景,那可以把View的背景转换成Bitmap,再存到Bundle里。但要注意:如果图片太大,可能会导致Bundle超出大小限制,引发异常,所以谨慎使用。
保存状态:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Drawable background = yourLinearLayout.getBackground(); // 只有当背景是BitmapDrawable时才能转换为Bitmap if (background instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) background).getBitmap(); // 把Bitmap转成字节数组存到Bundle,用JPEG压缩减小体积 ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); byte[] bgByteArray = stream.toByteArray(); outState.putByteArray("linear_bg", bgByteArray); } }
恢复状态:
@Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); byte[] bgByteArray = savedInstanceState.getByteArray("linear_bg"); if (bgByteArray != null) { // 把字节数组转回Bitmap,设置为背景 Bitmap bitmap = BitmapFactory.decodeByteArray(bgByteArray, 0, bgByteArray.length); yourLinearLayout.setBackground(new BitmapDrawable(getResources(), bitmap)); } else { // 没有保存的背景,再从网络加载 loadBackgroundWithPicasso(); } } @Override protected void onResume() { super.onResume(); // 如果View没有背景,就触发加载 if (yourLinearLayout.getBackground() == null) { loadBackgroundWithPicasso(); } }
内容的提问来源于stack exchange,提问作者Ening
相关产品推荐
相关产品推荐

