1

問題與問題標題中說明的一樣。實際上,我想將我的記錄中已有url的圖像加載到RecyclerView中,並同時將下載的圖像保存到數據庫中。我使用realm.ioGlide和我RecyclerViewAdapter是如下:LazyImage加載到RecyclerView +將LoadedImages保存到數據庫中

@Override 
public void onBindViewHolder(MyViewHolder holder, int position) { 
    final ProductModel obj = getData().get(position); 
    holder.data = obj; 
    holder.title.setText(obj.getTitle()); 
    if (obj.getImage() == null) { 

     Glide 
      .with(context) 
      .load(obj.getImageUrl()) 
      .fitCenter() 
      .placeholder(R.drawable.bronteel_logo) 
      .into(new GlideDrawableImageViewTarget(holder.icon) { 
      @Override 
      protected void setResource(GlideDrawable resource) { 
       // this.getView().setImageDrawable(resource); is about to be called 
       super.setResource(resource); 
       // here you can be sure it's already set 
       ((ProductsFragment) mFragment).saveImage(obj, resource); 
      } 
     }); 

    } else { 
     byte[] data = obj.getImage(); 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inMutable = true; 
     Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); 
     holder.icon.setImageBitmap(bmp); 
    } 
} 

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
    public TextView title; 
    public ImageView icon; 
    public ProductModel data; 

    public MyViewHolder(View view) { 
     super(view); 
     title = (TextView) view.findViewById(R.id.textView); 
     icon = (ImageView) view.findViewById(R.id.imageView); 

     view.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View view) { 
     if (data.getImage() != null) 
      activity.startActivity(new Intent(activity, ProductActivity.class).putExtra("id", data.getId())); 
    } 
} 

這裏就是我如何保存圖像:

public void saveImage(final ProductModel data, Drawable drw) { 
    new AsyncImagePersister(data).execute(drw); 
} 

private class AsyncImagePersister extends AsyncTask<Drawable, Void, byte[]> { 
     private final ProductModel data; 
     AsyncImagePersister(ProductModel data) { 
      this.data = data; 
     } 

     @Override 
     protected byte[] doInBackground(Drawable... drawables) { 
      ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
      Bitmap bmp = drawableToBitmap(drawables[0]); 
      bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); 
      return stream.toByteArray(); 
     } 

     @Override 
     protected void onPostExecute(final byte[] bytes) { 
      super.onPostExecute(bytes); 
      realm.executeTransaction(new Realm.Transaction() { 
       @Override 
       public void execute(Realm realm) { 
        data.setImage(bytes); 
       } 
      }); 
     } 

     public Bitmap drawableToBitmap (Drawable drawable) { 
      Bitmap bitmap = null; 

      if (drawable instanceof BitmapDrawable) { 
       BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; 
       if(bitmapDrawable.getBitmap() != null) { 
        return bitmapDrawable.getBitmap(); 
       } 
      } 

      if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { 
       bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel 
      } else { 
       bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 
      } 

      Canvas canvas = new Canvas(bitmap); 
      drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 
      drawable.draw(canvas); 
      return bitmap; 
     } 
    } 

然而,從互聯網加載首次圖像時(使用滑翔)它顯示不同地方的錯誤照片,另一方面在取出所有圖像後,保存的圖像到達正確的位置。

那麼我做錯了什麼?請幫忙。謝謝。

回答

1

錯位的圖像是由於意見正在被回收,所以加載位圖不一定屬於當前位置,而另一件事要考慮的是使用的AsyncTask一個RecyclerView內不會起到很好的和會導致UI中的滯後,並且最後一點,將byte []數組保存在模型中可能會導致OOM異常!

如果你想要做你的轉接器內需要長時間運行的任務,認爲使用服務IntentServiceThreadHandler的,所以你會被一個發送任務之一,the'd進行排隊並執行一個一個。

關於其脫機訪問圖片: 一種選擇是使用Glide.diskCacheStrategy方法和使用DiskCacheStrategy.ALL,所以原始圖像尺寸將被緩存,您可以在離線模式以後使用

第二種選擇是使用畢加索而不是Glide! ,以便您可以使用自定義的RequestHandler並下載圖像並將其保存在某處以便稍後可以訪問它,考慮內存管理都在您身邊,您應該處理它!

這裏是你的第二個選項提示: 創建類,從RequestHandler延伸:

CustomReqHandler : RequestHandler() { 

那麼你應該重寫兩個方法:canHandleRequest()負載()

canHandleRequest()您應該確定是否要處理當前的請求,因此請爲這些請求定義一個自定義方案,並檢查它是否是其中之一:

val scheme:String = data.uri.scheme 

第二個方法是負載(),這是在後臺線程執行,並返回一個結果對象,下載圖像,保存到某個地方,然後返回結果對象!

0

當您爲此使用Glide時,實際上並不需要將加載的圖像保存在數據庫中。滑動緩存一次自動和有效地加載的圖像。緩存是一個複雜的系統,如果您想了解更多有關Glide緩存的信息,可以查看here

現在,關於在錯誤的地方加載的圖像 - 這不應該發生。我發現你的onBindViewHolder沒有嚴重的錯誤,但是因爲我建議你不要在本地保存圖像,所以可以考慮簡單地使用Glide來加載圖像。

Glide 
    .with(context) 
    .load(obj.getImageUrl()) 
    .fitCenter() 
    .placeholder(R.drawable.bronteel_logo) 
    .into(holder.icon); 

只需要確認obj.getImageUrl()是否返回了正確的url。

+0

我需要將它們保存在數據庫中,因爲我需要在應用程序的其他部分離線加載它們。所以我不能依靠捕捉。如果您有任何想法,我該如何做,我會感謝您的幫助。否則,我知道捕捉選項。 –