I'm loading an image from a server to a list view item using picasso like this:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View participantView;
if(convertView == null) {
participantView = inflater.inflate(R.layout.participant_item, parent, false);
} else {
participantView = convertView;
}
TextView textView = (TextView) participantView.findViewById(R.id.participantName);
textView.setText(getItem(position).getName());
ImageView imageView = (ImageView) participantView.findViewById(R.id.participantImage);
String profilePic = getItem(position).getProfilePic();
if(!profilePic.equals("None")) {
Log.d("tom.debug", "creating picture for user: " + getItem(position).getName());
Picasso.with(this.context)
.load(urlToProfilePics + profilePic)
.placeholder(R.drawable.sample_0)
.resize(52, 52)
.into(imageView);
} else {
//load the place holder into the image view
Picasso.with(this.context).load(R.drawable.sample_0);
}
if(!getItem(position).isHere()) {
imageView.setColorFilter(Color.DKGRAY, PorterDuff.Mode.MULTIPLY);
}
return participantView;
}
The debug log under the if statement only fires for users that really have a profile picture. (Users that don't have will get a value of None
).
However, some of the other list view items (that don't have a profile pic) also get the picture loaded.
Another useful fact (I think): The items that get the bug changes when scrolling up and down the list.
I'm not sure what I'm missing here.
Make sure you call the cancelRequest everytime you are about to use Picasso on a getView() from the Adapter..
// 1st: reset the imageView
Picasso.with(this.context).cancelRequest(holder.imageView);
// 2nd start a new load for the imageView
Picasso.with(this.context).load(...).into(holder.imageView);
The reason is that the view you are reusing from the convertView parameter belongs to a previous row that was possibly already being loaded by Picasso for another picture.
This is only really necessary when using the convertView, if you have just inflated a new layout, it won't be needed..but you can call always to make your code easier.
Please refer the following codes.First is my grid_row.xml file. It is grid items layout file
<ProgressBar
android:layout_height="70dp"
android:layout_width="70dp"
android:id="@+id/myprogress"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_below="@+id/title" />
<View
android:layout_width="2dp"
android:layout_height="2dp"/>
<ImageView
android:layout_height="165dp"
android:id="@+id/imageView1"
android:layout_width="125dp"
android:scaleType="fitXY"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"/>
<View
android:layout_width="2dp"
android:layout_height="2dp"/>
<TextView
android:text="TextView"
android:layout_height="wrap_content"
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_below="@+id/imageView1"
android:textStyle="bold"
android:layout_marginTop="2dp"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:ellipsize="marquee">
</TextView>
<View
android:layout_width="2dp"
android:layout_height="2dp"/>
<TextView
android:text="TextView"
android:layout_height="wrap_content"
android:id="@+id/subTitle"
android:layout_width="wrap_content"
android:layout_below="@+id/title"
android:layout_marginTop="2dp"
android:layout_centerHorizontal="true"
android:textSize="18sp"
android:ellipsize="marquee">
</TextView>
</RelativeLayout>
Then Please go ahead with the adapter class for reference.
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by mpatil on 28/05/15.
*/
public class GridViewAdapter extends BaseAdapter
{
private ArrayList<String> listTitle;
private ArrayList<String> listSubTitle;
private ArrayList<String> imgp;
private Context activity;
ViewHolder view;
Configuration_Parameter m_config=Configuration_Parameter.getInstance();
public GridViewAdapter(Context activity,ArrayList<String> listTitle, ArrayList<String> subTitle,ArrayList<String> img)
{
super();
this.listTitle = listTitle;
this.imgp = img;
this.listSubTitle=subTitle;
this.activity = activity;
}
@Override
public int getCount()
{
// TODO Auto-generated method stub
return listTitle.size();
}
@Override
public String getItem(int position)
{
// TODO Auto-generated method stub
return (String) (String) view.imgViewFlag.getTag();
}
@Override
public long getItemId(int position)
{
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder
{
public ImageView imgViewFlag;
public TextView txtViewTitle;
public TextView txtViewSubTitle;
public ProgressBar pg;
public ViewHolder(View v)
{
}
public ViewHolder()
{
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
View participentView=convertView;
if(participentView == null || participentView.getTag() == null)
{
LayoutInflater inflater = null;
inflater=(LayoutInflater) parent.getContext().getSystemService(activity.LAYOUT_INFLATER_SERVICE);
view = new ViewHolder();
participentView = inflater.inflate(R.layout.grid_layout, null);
view.txtViewTitle = (TextView) participentView.findViewById(R.id.title);
view.txtViewSubTitle = (TextView) participentView.findViewById(R.id.subTitle);
view.pg=(ProgressBar)participentView.findViewById(R.id.myprogress);
view.imgViewFlag = (ImageView) participentView.findViewById(R.id.imageView1);
participentView.setTag(view);
}
else
{
view = (ViewHolder) participentView.getTag();
}
//download and display image from url
view.txtViewTitle.setText(listTitle.get(position));
view.txtViewSubTitle.setText(listSubTitle.get(position) + " subitem");
ImageLoader imageLoader = null;
imageLoader= ImageLoader.getInstance();
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.paceholder) // resource or drawable
.showImageOnFail(R.drawable.error_page_logo) // resource or drawable
.resetViewBeforeLoading(false) // default
.delayBeforeLoading(1000)
.cacheInMemory(true) // default
.cacheOnDisk(true) // default
.build();
m_config.imageLoader.displayImage(imgp.get(position), view.imgViewFlag,options,new SimpleImageLoadingListener()
{
@Override
public void onLoadingStarted(String imageUri, View v)
{
Log.i("Inside onLoadingStarted " + position,"Yes");
view.imgViewFlag.setVisibility(View.INVISIBLE);
view.pg.setVisibility(View.VISIBLE);
view.imgViewFlag.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View v, FailReason failReason)
{
Log.i("Inside onLoadingFailed " + position,"Yes");
view.pg.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View v, Bitmap loadedImage)
{
Log.i("Ins onLoadingComplete " + position, "Yes");
view.pg.setVisibility(View.GONE);
view.imgViewFlag.setVisibility(View.VISIBLE);
view.imgViewFlag.invalidate();
}
});
return participentView;
}
}
I am sure that this will help definitely. Thanks NOSTRA for such a great library. Thumbs Up...!!! Happy Coding... :)
In your getView() method change your Picasso code like this:
try {
Picasso.with(mActivity).
cancelRequest(holder.mImgCity);
Picasso.with(mActivity).
load(getItem(position).getBackgroundImg()).
error(R.drawable.image_1).
into(holder.mImgCity);
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
holder.mImgCity.setImageResource(R.drawable.image_1); //<-- Important line
}
Updated
Use Viewholder concept in your getView() method. You will get your everything done with this only.
I think I've been into the same situation. I suggest to use ViewHolder pattern for your adapter.
It will be something like this.
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View participantView = convertView;
if (participantView == null || participantView.getTag() == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// don't forget to inflate the same layout
participantView = inflater.inflate(R.layout.participant_item, null);
holder = getHolder(participantView);
assert participantView != null;
participantView.setTag(holder);
} else {
holder = (ViewHolder) participantView.getTag();
}
holder.textView.setText(getItem(position).getName());
String profilePic = getItem(position).getProfilePic();
if(!profilePic.equals("None")) {
Log.d("tom.debug", "creating picture for user: " + getItem(position).getName());
Picasso.with(this.context)
.load(urlToProfilePics + profilePic)
.placeholder(R.drawable.sample_0)
.resize(52, 52)
.into(holder.imageView);
} else {
//load the place holder into the image view
Picasso.with(this.context).load(R.drawable.sample_0);
}
if(!getItem(position).isHere()) {
holder.imageView.setColorFilter(Color.DKGRAY, PorterDuff.Mode.MULTIPLY);
}
resetViews(participantView);
return participantView;
}
void resetViews(View v) {
ViewHolder mHolder = new ViewHolder(v);
mHolder.textView.invalidate();
mHolder.imageView.invalidate();
}
static class ViewHolder {
TextView textView;
ImageView imageView;
}