In my application I'm using RecyclerView.Adapter with my custom Holder class. Each item consist of few TextView's and one ImageView(icon). Problem is that RecyclerView shows wrong Image after fast scrolling.
Example:
truth
NOT truth
So, my holder is:
public class CafeHolder extends RecyclerView.ViewHolder implements OnClickListener {
TextView itemName, itemType, itemMarksCount, itemCommentsCount, itemRating;
ImageView imgCafe;
ImageLoader imgLoader;
private Context context;
private int cafeId;
public CafeHolder(View view, Context context){
super(view);
this.context = context;
itemName = (TextView) view.findViewById(R.id.tvCafeName);
imgCafe = (ImageView) view.findViewById(R.id.imgCafe);
itemType = (TextView) view.findViewById(R.id.tvCafeType);
itemMarksCount = (TextView) view.findViewById(R.id.tvMarksCount);
itemCommentsCount = (TextView) view.findViewById(R.id.tvCommentsCount);
itemRating = (TextView) view.findViewById(R.id.tvRatingCount);
imgLoader = new ImageLoader(context);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(context, InfoActivity.class);
intent.putExtra(CafeDomain.ID, cafeId);
context.startActivity(intent);
}
public void setCafeId(int cafeId){
this.cafeId = cafeId;
}
And my RecyclerView.Adapter:
public class CafeAdapter extends RecyclerView.Adapter<CafeHolder> {
private Context context;
List<CafeDomain> listItems;
public CafeAdapter(List<CafeDomain> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public CafeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_cafe_item2, parent, false);
CafeHolder vh = new CafeHolder(v, context);
return vh;
}
#Override
public void onBindViewHolder(CafeHolder holder, int position) {
CafeDomain dItem = this.listItems.get(position);
holder.imgCafe.setImageDrawable(null);
holder.itemName.setText(dItem.getName());
ArrayList<TypeDomain> types = dItem.getTypes();
StringBuilder sbTypes = new StringBuilder();
for (int i = 0; i < types.size(); i++){
sbTypes.append(types.get(i).getName());
if (i!=types.size()-1)
sbTypes.append(", ");
}
holder.itemType.setText(sbTypes.toString());
if (!dItem.getIconUrl().isEmpty()){
holder.imgLoader.DisplayImage(dItem.getIconUrl(), holder.imgCafe); //load image from cache or web
}
else{
holder.imgCafe.setImageResource(R.drawable.icon200); //set default image
}
holder.itemMarksCount.setText(String.valueOf(dItem.getMarksCount()));
holder.itemCommentsCount.setText(String.valueOf(dItem.getCommentsCount()));
holder.itemRating.setText(String.valueOf(dItem.getRating()));
holder.setCafeId(listItems.get(position).getId());
}
#Override
public int getItemCount() {
return listItems.size();
}
}
I can see, that this code:
else{
holder.imgCafe.setImageResource(R.drawable.icon200); //set default image
}
is working, but two images are wrong anyway :(
UPDATE:
The problem is only when you fast scrolling list without image cache in disk. When we have cache, there is no problem here...
Hi i think your problem is here:
if (!dItem.getIconUrl().isEmpty()){
holder.imgLoader.DisplayImage(dItem.getIconUrl(), holder.imgCafe); //load image from cache or web
}
else{
holder.imgCafe.setImageResource(R.drawable.icon200); //set default image
}
I can offer you two solutions that may work. First check your imageUrl is null with TextUtils.isEmpty()
if (!TextUtils.isEmpty(dItem.getIconUrl())){
holder.imgLoader.DisplayImage(dItem.getIconUrl(), holder.imgCafe);
}
else{
holder.imgCafe.setImageResource(R.drawable.icon200); //set default image
}
İf this does not work, if you can set a image drawable for empty url or url loading fail just leave it to your image downloader and just use the code below:
holder.imgLoader.DisplayImage(dItem.getIconUrl(), holder.imgCafe);
Related
I have an ImageDownloader class which is used to download images from the API which works as I have tested displaying the images with an ImageView in my activity_main.xml file. I now want to display these images within a Listview so that it populates each image for each item using listview_images.xml layout. I've researched that a custom adapter file is needed to do this however I am very unfamiliar with custom adapter classes and I am unsure how they should be configured when using a downloaded image.
Code to save image and get the image from ImageDownloaderService and set it - MainActvity
for (int i = 0; i < displayFilmsNowShowingServiceActivity.getResults().length(); i++) {
try {
//Store each film result as a JSONObject in the Array
films.add(displayFilmsNowShowingServiceActivity.getResults().getJSONObject(i));
JSONObject getResults = displayFilmsNowShowingServiceActivity.getResults().getJSONObject(i);
result[i] = getResults.getString("film_name");
filmID[i] = getResults.getString("film_id");
filmArt[i] = getResults.getJSONObject("images").getJSONObject("poster").getJSONObject("1").getJSONObject("medium").getString("film_image");
//Create a file to save the image to using the imdb id of the film as a file name
String imagePath = this.getDir("MyfilmLib", Context.MODE_PRIVATE).getAbsoluteFile() + "/MyFilmLib/" + filmID[i] + ".jpg";
File file = new File(imagePath);
//If the file already exists then just display the image
if (file.exists()) {
ivFilmArt.setImageBitmap(BitmapFactory.decodeFile(imagePath));
} else {
//If the file doesn't exist then create and use an ImageDownloadService to download the image and
//save it to file
ImageDownloadService imageDownloadService = new ImageDownloadService(filmArt[i], imagePath);
//Call the addListener() method (which ImageDownloadService inherits from AbstractService) and pass this activity as an argument.
//The ImageDownloadService object can then call the ServiceComplete() method in this activity once the web service call has finished
imageDownloadService.addListener(this);
//Put the ImageDownloadService object on a new thread
imageThread = new Thread(imageDownloadService);
//Start the thread which will automatically call the run() method in the ImageDownloadService object
imageThread.start();
}
} catch (JSONException ex) {
result[i] = "Error";
ex.printStackTrace();
}
lvFilms.setAdapter(new ArrayAdapter<>(this, R.layout.listview_images, R.id.tv_images_text, result));
}
POJO Class
public class DisplayFilmsNowShowingPOJO {
private int filmID;
private String filmName;
public DisplayFilmsNowShowingPOJO (int filmID, String filmName){
this.filmID = filmID;
this.filmName = filmName;
}
public int getFilmID() {
return filmID;
}
public void setFilmID(int filmID) {
this.filmID = filmID;
}
public String getFilmName() {
return filmName;
}
public void setFilmName(String filmName) {
this.filmName = filmName;
}
}
Custom Adapter Attempt
public class DisplayFilmsNowShowingAdapter extends ArrayAdapter<DisplayFilmsNowShowingPOJO> {
private Context mContext;
private List<DisplayFilmsNowShowingPOJO> filmsList = new ArrayList<>();
public DisplayFilmsNowShowingAdapter(#NonNull Context context, #LayoutRes ArrayList<DisplayFilmsNowShowingPOJO> list) {
super(context, 0 , list);
mContext = context;
filmsList = list;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.listview_images,parent,false);
DisplayFilmsNowShowingPOJO currentFilm = filmsList.get(position);
ImageView iv_art = (ImageView)listItem.findViewById(R.id.iv_art);
iv_art.setImageResource(currentFilm.getFilmID());
TextView name = (TextView) listItem.findViewById(R.id.tv_images_text);
name.setText(currentFilm.getFilmName());
return listItem;
}
}
use this library for displaying image
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
now your adapter
public class DisplayFilmsNowShowingAdapter extends ArrayAdapter<DisplayFilmsNowShowingPOJO> {
private Context mContext;
private List<DisplayFilmsNowShowingPOJO> filmsList = new ArrayList<>();
public DisplayFilmsNowShowingAdapter(#NonNull Context context, #LayoutRes ArrayList<DisplayFilmsNowShowingPOJO> list) {
super(context, 0 , list);
mContext = context;
filmsList = list;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.listview_images,parent,false);
DisplayFilmsNowShowingPOJO currentFilm = filmsList.get(position);
ImageView iv_art = (ImageView)listItem.findViewById(R.id.iv_art);
// iv_art.setImageResource(currentFilm.getFilmID());
Glide
.with(iv_art.getContext())
.load(currentFilm.getFilmID())
.centerCrop()
.into(iv_art );
TextView name = (TextView) listItem.findViewById(R.id.tv_images_text);
name.setText(currentFilm.getFilmName());
return listItem;
}
}
you should be using a recyclerview for the above.
Check out this short tutorial on how to achieve the above
I have a working list view with images from the drawables folder, I have working code which takes an image and uploads it to my server etc, I have the url to fetch the image from the database and I now am stuck in how to add it into my already existing list View by automatically adding a new image from this link into the list view.
This is the 'timeline' list view which displays the pictures we already have
/**
* Method which creates the list view on screen and displays images
*/
public class Timeline extends Activity implements OnItemClickListener {
//global variables
String[] pic_names;
TypedArray profile_pics;
List<RowItem> rowItems;
ListView mylistview;
ImageView btnTakePic;
String[] uploaded_pic_name;
TypedArray pic_url;
//Overridden method to create the main layout
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timeline);
//set the global variables
//rowItems is now an arraylist
rowItems = new ArrayList<RowItem>();
//pic_names is set to the resource of pic_names
pic_names = getResources().getStringArray(R.array.pic_names);
uploaded_pic_name = getResources().getStringArray(R.array.uploaded_pic_name);
pic_url = getResources().obtainTypedArray(R.array.pic_url);
//profile_pics is now set to the resource of profile_pics
profile_pics = getResources().obtainTypedArray(R.array.profile_pics);
//gets the picture and name for each resource in the for loop array
for (int i = 0; i < pic_names.length; i++) {
RowItem item = new RowItem(pic_names[i], profile_pics.getResourceId(i, -1));
//adds items from the array
rowItems.add(item);
}
RowItem uploadedItem = new RowItem(uploaded_pic_name[0], pic_url.getResourceId(0, 0));
rowItems.add(uploadedItem);
//creates a new listview
mylistview = (ListView) findViewById(R.id.list);
CustomAdapter adapter = new CustomAdapter(this, rowItems);
mylistview.setAdapter(adapter);
//onclick listener on this main activity
mylistview.setOnItemClickListener(this);
btnTakePic = (ImageView) findViewById(R.id.btnTakePic);
// on click listener used to give function to the button when clicked.
btnTakePic.setOnClickListener(new View.OnClickListener() {
// onClick method defines what the function is
// Intent used to communicate to start
#Override
public void onClick(View v) {
Intent i = new Intent(Timeline.this, Camera.class);
startActivity(i);
}
});
}
//overridden method to show toast message on the picture
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String pic_name = rowItems.get(position).getPic_name();
Toast.makeText(getApplicationContext(), "" + pic_name,
Toast.LENGTH_SHORT).show();
}
}
This is the custom adapter class I had current for it
/**
* TODO
*/
public class CustomAdapter extends BaseAdapter {
//Instantiates getters for variables
Context context;
List<RowItem> rowItems;
//creates setters for variables
CustomAdapter(Context context, List<RowItem> rowItems) {
this.context = context;
this.rowItems = rowItems;
}
//Overridden method to get the size of the rows
#Override
public int getCount() {
return rowItems.size();
}
//Overridden method to get the item position from rowItems array returning the position
#Override
public Object getItem(int position) {
return rowItems.get(position);
}
//Overridden method to get the Item id return the position
#Override
public long getItemId(int position) {
return rowItems.indexOf(getItem(position));
}
/**
* private view holder class
*
*/
private class ViewHolder {
ImageView profile_pic;
TextView pic_name;
}
// Overriden method to insert image and its associated xml in the listview
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Instantiating local variables
ViewHolder holder;
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
//If the View is null create the layout
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
//set the textview and image view to required parameters
holder.pic_name = (TextView) convertView.findViewById(R.id.pic_name);
holder.profile_pic = (ImageView) convertView.findViewById(profile_pic);
convertView.setTag(holder);
//create a new viewholder and get the tag from the view
} else {
holder = (ViewHolder) convertView.getTag();
}
//getter for the position of the row
RowItem row_pos = rowItems.get(position);
//sets the position of the row
holder.profile_pic.setImageResource(row_pos.getProfile_pic_id());
holder.pic_name.setText(row_pos.getPic_name());
//return the view
return convertView;
}
}
These are the getters and setter for the images
public class RowItem {
private String pic_name;
private int profile_pic_id;
public RowItem(String pic_name, int profile_pic_id) {
this.pic_name = pic_name;
this.profile_pic_id = profile_pic_id;
}
//getter for the pic name
public String getPic_name() {
return pic_name;
}
//setter for the pic name
public void setPic_name(String pic_name) {
this.pic_name = pic_name;
}
//getter for the profile pic
public int getProfile_pic_id() {
return profile_pic_id;
}
//setter for the profile pic
public void setProfile_pic_id(int profile_pic_id) {
this.profile_pic_id = profile_pic_id;
}
}
Any help is much appreciated
Kindly show the code which you want to implement.
I have working code which takes an image and uploads it to my server
etc, I have the url to fetch the image from the database and i now
and on which event to implement(onClick, onItemClick etc...)
I will edit this later
Do this in, RecyclerView. There implementation is not difficult.. Your mistake is in viewholder... Read Recycler view and there will not any questions.
I've spent two days trying to find a solution for this problem and couldn't find it anywhere. My problem is: I have a List View in which each item has 4 text views and an ImageView. I'm fetching data from a website using Volley. The data loads normally and when a I scroll down everything works perfectly. The problem is when I scroll back. When I'm scrolling back the images and textviews have a 0.5 delay to appear (First I see the picture of the last item) and then the content is shown. I've already tried recyclerview and listview with viewholder. This "flick" persists in both solutions.
public class BigCategoryListViewAdapter extends BaseAdapter{
private Context context;
private String[] smallCatsList;
private News news;
private ImageLoader imageLoader;
static class myViewHolder{
TextView smallCatName;
RelativeLayout spinner;
ImageView newsImageView;
TextView newsTitle;
TextView newsContent;
}
public BigCategoryListViewAdapter(Context context, String[] smallCatsList){
this.context = context;
this.smallCatsList = smallCatsList;
this.imageLoader = ImageLoader.getInstance();
if(!this.imageLoader.isInited()) { this.imageLoader.init(ImageLoaderConfiguration.createDefault(context));}
}
#Override
public int getCount() {
return smallCatsList.length;
}
#Override
public Object getItem(int position) {
return smallCatsList[position];
}
#Override
public long getItemId(int position) {return 0;} //modificar aqui
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final myViewHolder mvh;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.bigcat_listview,null);
mvh = new myViewHolder();
mvh.smallCatName = (TextView) convertView.findViewById(R.id.bigcat_viewpager_smallcat);
mvh.spinner = (RelativeLayout) convertView.findViewById(R.id.spinner);
mvh.newsImageView = (ImageView) convertView.findViewById(R.id.bigcat_viewpager_imageView);
mvh.newsTitle = (TextView) convertView.findViewById(R.id.bigcat_viewpager_news_title);
mvh.newsContent = (TextView) convertView.findViewById(R.id.bigcat_viewpager_content);
convertView.setTag(mvh);
mvh.smallCatName.setText(smallCatsList[position]);
JSONObject params = new JSONObject();
try{
params.put("slug",smallCatsList[position]);
params.put("startIndex", 0);
params.put("endIndex", 0);
}catch (Exception e) {
Log.e(getClass().toString(), "Error setting params for communication with server");
e.printStackTrace();
}
Volley volley = Volley.getVolley(context);
volley.runRequest(Request.Method.POST, VolleyConstants.PROD_URL + VolleyConstants.NEWS_FETCH_ROUTE,
params, new Response.Listener<JSONObject>() {
//---------------------Volley------------------//
#Override
public void onResponse(JSONObject response) {
JSONArray responseArr = null;
try {
responseArr = response.getJSONArray("newsArr");
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < responseArr.length(); i++) {
try {
JSONObject object = responseArr.getJSONObject(i);
String photoURLString = object.getString("photo");
String titleString = object.getString("title");
String publisherString = object.getString("publisher");
String dateString = object.getJSONObject("date").getString("date");
String contentString = object.getString("contents");
String urlString = object.getString("url");
news = new News(photoURLString, titleString, publisherString, dateString, contentString,urlString);
} catch (Exception e) {
news = new News("Unknown", "Unknown", "Unknown", "Unknown", "Unknown","Unknown");
}
}
//tv2.setText(news.getNewsDate());
mvh.newsContent.setText(news.getNewsContent());
mvh.newsTitle.setText(news.getNewsHead());
//---------------------Image Loading------------------//
try {
URL url = new URL(news.getNewsPic());
imageLoader.loadImage(news.getNewsPic(), new ImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
mvh.newsImageView.setImageBitmap(loadedImage);
mvh.spinner.setVisibility(View.GONE);
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
}
});
}catch(Exception e){
mvh.newsImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.nopic));
mvh.spinner.setVisibility(View.GONE);
}
}
}, new CustomErrorListener("ERROR"));
return convertView;
}
This is my adapter. My question is if there is a way to remove this delay to show the content? Or is my problem with network or the listview itself?
I just wanna load all the content for once and then the user can scroll up and down without having to refresh the content everytime.
You're loading the content every time getView is called, that's why it's loading like that. Separate the Volley request from the getView, it should be outside of the adapter entirely, not called upon every load of every piece of the list. You have your News Objects, you can pass an ArrayList to the adapter and fill it from there, that will fix your loading issue. Also, you're calling volley in the Main thread instead of a new thread, you should separate the two, and populate the ListView adapter upon completion of the content being loaded.
One, the ViewHolder pattern example should be something more like this:
if (convertView == null) {
convertView = inflater.inflate(R.layout.bigcat_listview,null);
mvh = new myViewHolder();
//... rest of your code
} else {
mvh = (myViewHolder) convertView.getTag();
//... rest of your code
}
Second, the major Volley loading stuff should not be in the adapter, but processed elsewhere beforehand then passed in. This example should help you out a lot.
I have a problem to updae my recycle when updating scroll up/down.
I have 3 (Custom ítems with respect views) but my onBindViewHolder only calls 2, when I try down list, my list not update correctly aparently It makes a cut (0.2 sec)
I don't know why not update correctly with 3 (ítems with 3 images)
My holder : (Why count 2?) but I when down, count 3 ...
public class CAPusheenAdapter_Fragment_0_7 extends RecyclerView.Adapter<CAPusheenAdapter_Fragment_0_7.ViewHolder> {
private ArrayList<CustomItem_0_ALL> pusheenArrayList;
private int itemLayout;
private Context context;
DBHelper db ;
RecyclerView recyclerView;
public CAPusheenAdapter_Fragment_0_7(ArrayList<CustomItem_0_ALL> data, int itemLayout, Context context, RecyclerView recyclerView){
setHasStableIds(true);
this. pusheenArrayList = data;
this. itemLayout = itemLayout;
this. context = context;
db = new DBHelper(context);
this. recyclerView = recyclerView;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ArrayList<TextView> allTextViews;
//public TextView text1,text2,text3,text4,text5,text6,text7;
public LinearLayout l1;
public ViewHolder(View itemView) {
super(itemView);
int numOfTextViews=6;
allTextViews = new ArrayList<TextView>(); allTextViews.add(0,null);
l1 = (LinearLayout)itemView.findViewById(R.id.l1);
for(int i=1;i<=numOfTextViews;i++){
allTextViews.add(i,Config.getViewsComplext(context,itemView, "text" + i));
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//final int itemPosition = Fragment_0.recyclerView.getChildPosition(view); // todo SOO COOL LINE !
final int itemPosition = recyclerView.getChildPosition(view); // todo SOO COOL LINE !
//Toast.makeText(context, "No plantejada", Toast.LENGTH_SHORT).show();
//MainActivity.FragmentReutil2(new Class[]{Fragment_0_4_1.class}, 0, context);
}
});
}
}
#Override
public CAPusheenAdapter_Fragment_0_7.ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
Config.totalConfigFull2(context, itemLayoutView);
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(CAPusheenAdapter_Fragment_0_7.ViewHolder viewHolder, int position) {
CustomItem_0_ALL pusheen = pusheenArrayList.get(position);
ArrayList<String> texts = new ArrayList<>();
texts.add(0,null);
texts.add(1,pusheen.getText1());
texts.add(2,pusheen.getText2());
texts.add(3,pusheen.getText3());
texts.add(4,pusheen.getText4());
texts.add(5,pusheen.getText5());
texts.add(6,pusheen.getText6());
for ( int i = 1 ; i < viewHolder.allTextViews.size() ; i+=1 ){
if(texts.get(i).length()>0){
viewHolder.allTextViews.get(i).setText(texts.get(i));
viewHolder.allTextViews.get(i).setVisibility(View.VISIBLE);
}else{
viewHolder.allTextViews.get(i).setVisibility(View.GONE);
}
}
//viewHolder.l1.setBackgroundResource(pusheen.getImg());
int w =Config.getWigthHeightScreen(context)[0];
int h =Config.getWigthHeightScreen(context)[1];
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(w, (int) (h/2.5));
viewHolder.l1.setBackgroundResource(pusheen.getImg());
viewHolder.l1.setLayoutParams(lp);
}
#Override
public int getItemCount() {
return this.pusheenArrayList.size();
}
}
Note : only call/count elements from screen not call out elements, only call when you move list up/down
I found problem :
This is the problem : and solution
AsyncTask loading image RecyclerView
im try to make listview with dynamic images, using asyntask its download image and set into listview. my problem is while scroll down images get randomly changed..
class ps1 extends ArrayAdapter<String> {
Context context;
String[] images1;
List mList;
String[] namearray;
String[] rating;
static class ViewHolder {
ImageView localImageView1;
ImageView localImageView2;
ImageView localImageView3;
}
ps1(Context paramContext, String[] paramArrayOfString1, String[] paramArrayOfString2, String[] paramArrayOfString3) {
super(paramContext, R.layout.list2, R.id.imageView1, paramArrayOfString1);
this.context = paramContext;
this.images1 = paramArrayOfString3;
this.namearray = paramArrayOfString1;
this.rating = paramArrayOfString2;
}
public View getView(int paramInt, View paramView, ViewGroup paramViewGroup) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
ViewHolder viewHolder = new ViewHolder();
if (paramView == null) {
paramView = inflater.inflate(R.layout.list2, paramViewGroup, false);
}
viewHolder.localImageView1 = (ImageView) paramView
.findViewById(R.id.imageView1);
viewHolder.localImageView2 = (ImageView) paramView
.findViewById(R.id.imageView2);
viewHolder.localImageView3 = (ImageView) paramView
.findViewById(R.id.imageView3);
viewHolder.localImageView1.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView2.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView3.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.localImageView1.setTag(this.namearray[paramInt]);
new LoadImage().execute(viewHolder.localImageView1);
viewHolder.localImageView2.setTag(this.rating[paramInt]);
new LoadImage().execute(viewHolder.localImageView2);
viewHolder.localImageView3.setTag(this.images1[paramInt]);
new LoadImage().execute(viewHolder.localImageView3);
return paramView;
}
}
class LoadImage extends AsyncTask<Object, Void, Bitmap> {
private ImageView imv;
private Bitmap download_Image(String paramString) {
Bitmap localBitmap = null;
try {
Object localObject = null;
localBitmap = BitmapFactory
.decodeStream(((HttpURLConnection) new URL(paramString)
.openConnection()).getInputStream());
localObject = localBitmap;
if (localObject != null) {
return localBitmap;
}
} catch (Exception e) {
}
return localBitmap;
}
protected Bitmap doInBackground(Object... paramVarArgs) {
this.imv = ((ImageView) paramVarArgs[0]);
Log.d("fsdf", (String) this.imv.getTag());
return download_Image((String) this.imv.getTag());
}
protected void onPostExecute(Bitmap paramBitmap) {
this.imv.setImageBitmap(paramBitmap);
}
}
I have also experienced the same . I am also searching for a right solution . As far as i have searched , i came to know that ListView clears the previous view while scrolling down and re-loads it when you scroll back . So while scrolling up and down, your images may get re-cycled and mis-aligned . ( I am also waiting for the correct solution ) .
But i have tackled it using SmartImageView , which is a library that directly downloads the image and sets it to the ImageView . It will maintain the images in cache and so you could get the right images .
Comparatively this was faster too .
Try this snippet code which i have used in application and it's working fine in my application and i am sure it will work at your end.
In my condition i am retrieving images and some data from server and maintain all images on list scrolling fine.
class OfferCustomListAdapter extends ArrayAdapter<String>
{
private Context context;
Boolean OddNumber;
ArrayList<String> getDealID = new ArrayList<String>();
ArrayList<String> getInAdpterUNamedlist = new ArrayList<String>();
ArrayList<String> getShopNData = new ArrayList<String>();
ArrayList<String> getUserFav = new ArrayList<String>();
ArrayList<String> getTotalAmt = new ArrayList<String>();
ArrayList<String> getDealImage = new ArrayList<String>();
ArrayList<Boolean> getBoolnState = new ArrayList<Boolean>();
//String Oflist[] ;
int favCount=0;
public OfferCustomListAdapter(Context context,ArrayList<String> dealIdlist, ArrayList<Boolean> AddBoolnList, ArrayList<String> dealNamelist,ArrayList<String> ShopNList,ArrayList<String> UserFave,ArrayList<String> TotalAmt,ArrayList<String> ImageList) {
super(context, android.R.layout.simple_list_item_1,dealNamelist);
this.context=context;
//Oflist = getFolwerUNamelis;
getDealID = dealIdlist;
getInAdpterUNamedlist = dealNamelist;
getShopNData = ShopNList;
getUserFav = UserFave;
getTotalAmt = TotalAmt;
getDealImage = ImageList;
getBoolnState = AddBoolnList;
}
#Override
public View getView(final int pos, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(this.context);
//view = inflater.inflate(R.layout.offer_custom_list, parent,false);
view = inflater.inflate(R.layout.reservatin_row, parent,false);
holder = new ViewHolder();
//holder.FollowrName = (TextView) view.findViewById(R.id.OfferNameTxt);
holder.DealName = (TextView) view.findViewById(R.id.tv_name);
holder.ShopName = (TextView) view.findViewById(R.id.tv_address);
holder.FavBtn = (ImageView) view.findViewById(R.id.Ofr_FavBtn);
holder.listLayout = (LinearLayout) view.findViewById(R.id.OfferListLayout);
holder.profile_image = (ImageView)view.findViewById(R.id.profile_img);
holder.OfferAmtBtn =(Button)view.findViewById(R.id.TotalOfrBtn);
//holder.FavBtn = (ImageView) view.findViewById(R.id.offerFavBtn);
holder.FavBtn.setTag(pos);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if ( pos % 2 == 0 ){
System.out.println("You entered an even number. "+pos % 2);
holder.listLayout.setBackgroundResource(R.drawable.offer_list_bg);
}else{
System.out.println("You entered an odd number.");
holder.listLayout.setBackgroundResource(R.drawable.special_offer_bg);
}
/*if(getUserFav.get(pos).equals("0")){
//BolArraylist.add(false);
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
}else{
//BolArraylist.add(true);
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
}*/
holder.DealName.setText(getInAdpterUNamedlist.get(pos));
holder.ShopName.setText(getShopNData.get(pos));
holder.OfferAmtBtn.setText("$"+getTotalAmt.get(pos));
imgLoader.DisplayImage(getDealImage.get(pos), holder.profile_image);
holder.FavBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (isNetworkAvailable()) {
if(!userid.equals("")){
Offer_ID = getDealID.get(pos);
GUsrFavState = getUserFav.get(pos);
if(GUsrFavState.equals("0")){
GUsrFavState="1";
getUserFav.remove(pos);
getUserFav.add(pos, "1");
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
getBoolnState.set(pos, true);
new Call_OfferFavWS().execute();
}else{
GUsrFavState="0";
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
getUserFav.remove(pos);
getUserFav.add(pos, "0");
getBoolnState.set(pos, false);
new Call_OfferFavWS().execute();
}
}else{
Intent CallSignIn = new Intent(DollarMainActivity.this,SingInActivity.class);
startActivity(CallSignIn);
}
} else {
Toast alrtMsg = Toast.makeText(DollarMainActivity.this, "No network connection available !!!", Toast.LENGTH_LONG);
alrtMsg.setGravity(Gravity.CENTER, 0, 0);
alrtMsg.show();
}
}
});
if(getBoolnState.get(pos)){
holder.FavBtn.setBackgroundResource(R.drawable.fav_active_btn);
}else{
holder.FavBtn.setBackgroundResource(R.drawable.fav_btn);
}
return view;
}
class ViewHolder {
public TextView DealName,ShopName;
public ImageView FavBtn, profile_image;
public LinearLayout listLayout;
public Button OfferAmtBtn;
}
}
Hope it will help you.
if you need any help pls let me know.