I have a ListView which I am filling from server. Everything works fine but the single problem is that the downloaded images are shown in wrong item positions when scroll. Only after a few seconds then it shows the correct image on the right position.
Here is my ArrayAdapter class, which includes the AsynchTask:
public class ApplicationAdapter extends ArrayAdapter<Application> {
private List<Application> items;
public ApplicationAdapter(Context context, List<Application> items) {
super(context, R.layout.app_custom_list, items);
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.app_custom_list, null);
}
Application app = items.get(position);
if (app != null) {
ImageView imageView = (ImageView) v.findViewById(R.id.appIcon);
TextView titleText = (TextView) v.findViewById(R.id.titleTxt);
if (imageView != null) {
String path_image = app.getImagePath();
// Call AsynchTask to load image into ImageView from path
DownloadImageTask1 d = new DownloadImageTask(imageView);
d.execute(path_image);
}
if (titleText != null) {
titleText.setText(app.getTitle());
}
}
return v;
}
private class DownloadImageTask1 extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask1(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(getRoundedCornerBitmap(result));
}
}
Can somebody please guide me to the right direction? I am already working for days to solve this issue. Thanks!!!
This is because the ImageView
is reused when the listview
is scrolled. show a loading image in the listview
onPreExecute
. it woluld be better if you use some library like picasso for this. as it does all the work for you including saving the image in the catch
You should use another class for holding your objects, it helps you keep a good reference once set.
And it's best you change your adapter a little bit.
It's best you get a reference to your layoutInflater once , since getView is called for every item in the listview.
So declare your layoutInflater for the whole class and get a reference only once
For example :
private LayoutInflater inflater;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageHolder holder = new ImageHolder();
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView == null){
convertView = inflater.inflate(R.layout.fragment_list_item_transition, null);
ImageView imageView = (ImageView) convertView.findViewById(R.id.appIcon);
TextView titleText = (TextView) convertView.findViewById(R.id.titleTxt);
holder.image = imageView;
holder.title = titleText;
convertView.setTag(holder);
}else{
holder = (ImageHolder) convertView.getTag(position);
}
Application app = items.get(position);
if (app != null) {
holder.title.seText(app.getTitle());
String path_image = app.getImagePath();
// Call AsynchTask to load image into ImageView from path
DownloadImageTask1 d = new DownloadImageTask1(holder.imageView);
d.execute(path_image);
}
return convertView;
}
private static class ImageHolder{
ImageView image;
TextView title;
}
You can also try UniversalImageLoader library to load images.. Try this
ImageLoader.getInstance().displayImage(url, holder.imgView, options);
to load images inside adapter..
Use DisplayImageOptions as follows inside constructor of adapter
options = new DisplayImageOptions.Builder()
.showImageOnLoading(android.R.color.transparent)
.showImageForEmptyUri(android.R.color.transparent)
.showImageOnFail(android.R.color.transparent)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
and add
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
inside onCreateView/onCreate of fragment/activity contaning the list
Try something like this...
replace
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.app_custom_list, null);
}
with
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.app_custom_list, null);
convertView.setTag(v);
} else {
v = (View) convertView.getTag();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.