Lukas Plevac Developer Lukas Plevac Developer - 12 days ago 5
Android Question

Image from url in ListView random image error

my problem is with loading image for listview in AsyncTask. App output is listview with textview Which works perfectly, but ImageView loads almost random images which in some items changes to other image (Sometimes it likes as loop).

logcat -s "test" -> caught nothing

BinderData:

package cz.www3.tech_apps.cinetube.cinetube;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class Binderdatakomunita extends BaseAdapter {

LayoutInflater inflater;
List<HashMap<String,String>> komunitaarray;
ViewHolder holder;


public Binderdatakomunita() {

}

public Binderdatakomunita(Activity act, List<HashMap<String,String>> map) {

this.komunitaarray = map;

inflater = (LayoutInflater) act
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}


public int getCount() {
return komunitaarray.size();
}

public Object getItem(int arg0) {
return null;
}

public long getItemId(int position) {
return 0;
}
public int position;

public View getView(int position, View convertView, ViewGroup parent) {

View vi=convertView;
if(convertView==null){

vi = inflater.inflate(R.layout.lide, parent, false);
holder = new ViewHolder();

holder.jmeno = (TextView)vi.findViewById(R.id.jmeno);
holder.akce = (TextView)vi.findViewById(R.id.akce);
holder.id = (TextView)vi.findViewById(R.id.id);
holder.profilovkaimg = (ImageView)vi.findViewById(R.id.profilovka);

vi.setTag(holder);
}
else{

holder = (ViewHolder)vi.getTag();
}
holder.jmeno.setText(komunitaarray.get(position).get("jmeno"));
if (komunitaarray.get(position).get("akce") != null){
holder.akce.setText(komunitaarray.get(position).get("akce"));
} else {
holder.akce.setText("Neznámá akce");
}
try {
new DownLoadImageTask(holder.profilovkaimg).execute(komunitaarray.get(position).get("obrazek"));
} catch (Exception e) {
Log.e("test", "exception", e);
}
holder.id.setText(Integer.toString(position));

return vi;
}

static class ViewHolder{

TextView jmeno;
TextView akce;
TextView id;
ImageView profilovkaimg;
}

private class DownLoadImageTask extends AsyncTask<String,Void,Bitmap>{
ImageView imageView;

public DownLoadImageTask(ImageView imageView){
this.imageView = imageView;
}

public Bitmap scaleDown(Bitmap realImage, float maxImageSize,
boolean filter) {
float ratio = Math.min(
(float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());

Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width,
height, filter);
return newBitmap;
}

public Bitmap getCroppedBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);

final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getWidth() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false);
//return _bmp;
return output;
}

protected Bitmap doInBackground(String...urls){
String urlOfImage = urls[0];
Bitmap logo = null;
try{
URLConnection con = new URL( urlOfImage ).openConnection();
con.connect();
InputStream is = con.getInputStream();
logo = BitmapFactory.decodeStream(is);
is.close();
}catch(Exception e){
e.printStackTrace();
}
try{
return getCroppedBitmap(scaleDown(logo, 100, true));
}catch(Exception e){
return null;
}
}

protected void onPostExecute(Bitmap result){
imageView.setImageBitmap(result);
}
}
}

Answer

When you scroll your screen, the ListView/RecyclerView creates and destroys views as needed. Consider the case where an AsyncTask was fired to get an image but the image went off screen. Now, the adapter may try to recycle that view, but the AsyncTask still holds a reference to it, which can cause memory leaks leading to such issues. More information can be found in the documentation.

Consider using an image library such as Picasso to load your image easily instead of a custom AsyncTask.

Comments