This is very common. And in addition to the slowness, you can catch the famous Exception OutOffMemory
.
To prevent this, you can solve two (simple) steps within your Adapter:
1)- Place all image uploads inside a AsyncTask
. This causes you to take away from your main thread the job of uploading heavy images and block the user experience. And in addition, you can cancel the execution of this AsyncTask
case, for example, the user of a very fast scroll:
Add a AsyncTask
inside your Viewholder:
...
private class ViewHolder{
public ImageView image;
public AsyncTask<Void, Void, Bitmap> asyncTask;
...
}
Within the method getView()
of your Adapter:
...
//Previnindo o recycle de view
if (holder.asyncTask != null) {
holder.asyncTask.cancel(true);
holder.asyncTask = null;
}
//Previnido que a imagem "pisque" caso de um scroll muito rápido;
holder.image.setImageResource(R.drawable.someDrawable);
final ImageView image = holder.image;
holder.asyncTask = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
//Aqui você faz as implementações a seguir
}
@Override
protected void onPostExecute(Bitmap bitmap) {
image.setImageBitmap(bitmap);
}
};
holder.asyncTask.execute();
2) Within your Asynctask, you can use a property called inSampleSize
, that makes the Code of your image at a lower resolution, as if it were a "sample" of your image. For example, a 2048x1536 image using inSampleSize as 4 produces an image of approximately 512x384. This loaded image uses only 0.75MB of memory instead of 12MB of the original image size. You can use this property within a BitmapFactory.Options
:
//Dentro de sua AsyncTask criada
@Override
protected Bitmap doInBackground(Void... params) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
/*Reduzindo a qualidade da imagem para preservar memoria.
* Aqui você pode testar a redução que melhor atende sua necessidade
*/
options.inSampleSize = 2;
return BitmapFactory.decodeStream(new FileInputStream(imagePath), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Sources:
Loading Large Bitmaps Efficiently
Processing Bitmaps Off the UI Thread
Wouldn’t it be more appropriate to do this outside the app? I mean, you can convert the images to a lower resolution manually, and then use them in the application (instead of the current ones, or together - keeping two copies of each image, one for thumbnail display and the other for normal display). The software conversion also takes time and you will end up having the same result (if not worse).
– Luiz Vieira
This is not feasible, I am creating an automated system, I can’t keep forcing the user to edit the image to put in the application.
– Skywalker
Ah, it is the user who sends the image then. Sorry, it was not clear in the question.
– Luiz Vieira