Reputation: 1968
I am using this ArrayAdapter
to load thumbnail images asynchronously
public class CourierArrayAdapter extends ArrayAdapter<Courier> {
private Map<String, Bitmap> bitmaps = new HashMap<>();
private static class ViewHolder{
TextView txtViewName;
TextView txtViewNumber;
CircleImageView imageViewPic;
int position;
}
public CourierArrayAdapter(Context context, List<Courier> requests) {
super(context, -1, requests);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
Courier request = getItem(position);
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(R.layout.list_item_courier, parent, false);
viewHolder.txtViewName = (TextView) convertView.findViewById(R.id.textView_list_item_courier_name);
viewHolder.txtViewNumber = (TextView) convertView.findViewById(R.id.textView_list_item_courier_number);
viewHolder.imageViewPic = (CircleImageView) convertView.findViewById(R.id.imageView_list_item_courier_pic);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txtViewName.setText(request.name);
viewHolder.txtViewNumber.setText(request.number);
viewHolder.position = position;
if (bitmaps.containsKey(request.picURL)) {
viewHolder.imageViewPic.setImageBitmap(bitmaps.get(request.picURL));
}
else
new LoadImageTask(position, viewHolder).execute(request.picURL);
return convertView;
}
private class LoadImageTask extends AsyncTask<String, Void, Bitmap> {
private int mPosition;
private ViewHolder mViewHolder;
public LoadImageTask(int position, ViewHolder holder) {
this.mPosition = position;
this.mViewHolder = holder;
}
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
HttpURLConnection connection = null;
try {
URL url = new URL(params[0]); // create URL for image
connection = (HttpURLConnection) url.openConnection();
InputStream inputStream = connection.getInputStream();
try {
bitmap = BitmapFactory.decodeStream(inputStream);
bitmaps.put(params[0], bitmap);
} catch (Exception e) {
e.printStackTrace();
}
finally {
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect(); // close the HttpURLConnection
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (mViewHolder.position == mPosition)
mViewHolder.imageViewPic.setImageBitmap(bitmap);
}
}
}
As you can see, I am loading these images using a picURL
property and I am loading them using a private AsyncTask
class. The problem is that I get OutOfMemoryException
an this error message:
FATAL EXCEPTION: AsyncTask #3
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:304)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 37602252 byte allocation with 16776720 free bytes and 29MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:863)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:839)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:877)
at net.faraznet.provider.arrayadapters.CourierArrayAdapter$LoadImageTask.doInBackground(CourierArrayAdapter.java:99)
at net.faraznet.provider.arrayadapters.CourierArrayAdapter$LoadImageTask.doInBackground(CourierArrayAdapter.java:76)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
The images are a bit large in size and if possible, it is not an issue that I resize them before loading them into memory, but the problem is that I don't know how to achieve this task or any other solutions to my problem
Upvotes: 0
Views: 85
Reputation: 1223
recently i have achieved this, so the best way to achieve this use Picasso, user this code in your array adapter
Picasso.with(this)
.load(url)
.into(new Target() {
@Override
public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
/* Save the bitmap or do something with it here */
//Set it in the ImageView
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
});
Use this in manifest before Application.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
Add the following line in dependencies or Gradle.
compile 'com.squareup.picasso:picasso:2.5.2'
for information go through the following links
http://square.github.io/picasso/
https://github.com/square/picasso
i hope it will helpful.
Upvotes: 0
Reputation: 5655
If you can use custom libraries, then use Glide
.
Glide is more efficient in performance and memory management with respect to Images than Picasso
. check this comparison
All the steps are clearly defined in github to use Glide in application
Alternatively you can increase heap size of application by android:largeHeap="true" . But this will not work on any pre Honeycomb devices
On pre 2.3 devices, you can use the VMRuntime class. but this will not work on Gingerbread and above.
VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);
Upvotes: 1
Reputation: 134
Add the below line in dependencies.
compile 'com.squareup.picasso:picasso:2.5.2'
and below code to get the image in ImageView.
Picasso.with(context)
.load(url)
.into(imageView)
And you are good to go. For more information, check this link.
Upvotes: 0
Reputation: 4023
You can use a third party library named Glide , which is recommended by google . To add this library , add the the following dependency in your build.gradle file , in module app .
dependencies {
compile 'com.github.bumptech.glide:glide:3.5.2'
compile 'com.android.support:support-v4:22.0.0'
}
And then you can simply load image in following way
Glide.with(context)
.load(request.picURL)
.into(viewHolder.imageViewPic);
Upvotes: 0