0

I'm workin with Volley API in my WebServices, and then I'll write the data in with SQLITE.

Webservices that comes with a JSON with many itens, each of then has data and a image, and I need to keep this image in my cache to display offline in a ListView and later on a detail screen. In the future the user will clean these itens and clear the imagens of them too.

Well, how can I save these images in my local DB and link with each Item that I have from the JSON?

I will be, in 90% of the time, offline. I will only stay online for synchronizing and download the updated server items.

LMaker
  • 1,444
  • 3
  • 25
  • 38
  • You can use Universal Image Loader or picasso; these libraries manage cache of image automatically and are very customizables – crgarridos Jun 23 '16 at 14:25
  • I heard about picasso but I don't know if picasso can display images offline – LMaker Jun 23 '16 at 14:28
  • Actually both of them can do it. You load your images once and the library manage all (internally) for you. Picasso with none configuration and UIL with a first initialisation in your app class – crgarridos Jun 23 '16 at 14:32

3 Answers3

2

For dealing with images in Android the benchmark is to use Picasso library. It takes care of:

  • Handling ImageView recycling and download cancelation in an adapter;
  • Complex image transformations with minimal memory use;
  • Automatic memory and disk caching.

Besides that, if you're going to display images in lists and need animation to enhance your UI, I strongly recommend changing from ListView to RecyclerView. It is not recommended to store the images in the DB, you would lose time converting this from/to blobs (check here and here). Said that, what I suggest is:

  1. Use Picasso to load the images from the URL provided in the JSON;
  2. Implement a Custom target to handle the image file downloaded by Picasso;
  3. Save the image in a folder inside your app directory;
  4. Use RecyclerView to display the images; (optional)

If you need a project example where those things are done, you can check this. In this project I follow the approache I've described above. You can download the app from the store and see how it will download the images.

Quicky-guide:

  1. To use Picasso add this to you module's gradle file: compile 'com.squareup.picasso:picasso:2.5.2'

  2. Create a class that implements import com.squareup.picasso.Callback;:

    public class ImageWarehouse implements Callback { private static final String TAG = "ImageWarehouse";

    private String mDirectory;
    private String mFileName;
    private ImageView mContainer;
    @Inject
    App mApplication;
    
    public ImageWarehouse(String fileName, ImageView container, String directory) {
        this.mFileName = fileName;
        this.mContainer = container;
        this.mDirectory = directory;
        this.getStorageDir();
    }
    
    @Override
    public void onSuccess() {
        if (this.isExternalStorageWritable()) {
            final Bitmap bitmap = ((BitmapDrawable) this.mContainer.getDrawable()).getBitmap();
            new AsyncTask<Void, Void, File>() {
                @Override
                protected File doInBackground(Void... params) {
                    File file = null;
                    try {
                        file = new File(ImageWarehouse.this.getStorageDir().getPath().concat("/").concat(ImageWarehouse.this.mFileName.concat(Constants.MEDIA_EXTENSION)));
                        file.createNewFile();
                        FileOutputStream ostream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
                        ostream.close();
                    } catch (Exception e) {
                        Log.e(TAG, "External Storage is not available");
                    }
                    return file;
                }
            }.execute();
        } else {
            Log.e(TAG, "External Storage is not available");
        }
    }
    
    @Override
    public void onError() {
    
    }
    
    public boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;
    }
    
    public File getStorageDir() {
        File file = new File(Environment.getExternalStorageDirectory(), Constants.MEDIA_DIRECTORY.concat(this.mDirectory));
        if (!file.mkdirs()) {
        }
        return file;
    }
    

    }

  3. Call Picasso in order to display the image in the layout and save it to the specified path:

    Picasso .load(URL) .fit() .centerCrop() .into(viewHolder.cover, new ImageWarehouse( name, viewHolder.cover, Constants.MEDIA_CHARACTER ) );

Community
  • 1
  • 1
E. Fernandes
  • 3,889
  • 4
  • 30
  • 48
1

You can user Android-Universal-Image-Loader it is also cache image in memory. it is show from cache when next time same url used in imageloader for get image

see below link for complete source code of Universal Image Loader Example.

Android - Universal Image Loader

Dedaniya HirenKumar
  • 2,980
  • 2
  • 22
  • 25
0

You can save your images in Sqlite as blob and can retrieve it when required. Create table as

create table sometable(id integer primary key autoincrement,photo BLOB);

And save the image as

//convert image into byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();  
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.common)).getBitmap();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);   
byte[] photo = baos.toByteArray();

//And now store this image
ContentValues initialValues = new ContentValues();   
initialValues.put("photo",photo);
return db.insert("sometable", null, initialValues);

And retrieve image as

Cursor cur=your query;
while(cur.moveToNext())
{
   byte[] photo=cur.getBlob(index of blob cloumn);
}
Zaartha
  • 1,106
  • 9
  • 25