Images in list view jumping from row to row - java

I am using a ListView with images, also I have an image loader. The problem is that when there is a fast scrolling the images appears on wrong rows, after short time when the scrolling stops every thing gets back in place.
Here is my adapter:
public class MyAdapter extends ArrayAdapter<MyObj>
{
int layoutResourceId;
List<MyObj> data;
Activity activity;
int rowViewId;
public MyAdapter(Activity activity, int layoutResourceId, List<MyObj> data)
{
super(activity, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.activity = activity;
this.data = data;
rowViewId = R.layout.my_layout.xml;
}
public static class ViewHolder
{
public TextView title;
public ImageView image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
ViewHolder holder;
if (row == null)
{
LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(rowViewId, null);
holder = new ViewHolder();
holder.title = (TextView) row.findViewById(R.id.title);
holder.image = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
}
else
{
holder = (ViewHolder) row.getTag();
}
final MyObj obj = data.get(position);
if (event != null)
{
holder.title.setText(event.getTitle());
ImageLoader imageLoader = new ImageLoader();
imageLoader.loadImageFromAppServer(obj.getImageName(), holder.image);
}
return row;
}
}
Is there any thing I can do to prevent this unwanted behaviour?

Your image is being loaded asynchronously by loadImageFromAppServer. When it arrives from the server, your holder.image object is already reused by another row that doesn't represent the same data it did when you asked your ImageLoader object to download the image. You need to implement a way to tell the ImageLoader object to cancel the previous download request.

Related

Holder vs RecylerView.ViewHolder

I have ListView with Adapter, and also use holder. but later I read about recyclerView.ViewHolder and now confused, Is it different with the one I've been using right now? I mean for the optimization purpose, I want to know if using holder only is not good enough without using recyclerView.
public class NewsAdapter extends ArrayAdapter<News> {
Context context;
List<News> myList;
public NewsAdapter(Context context, int resource, List<News> objects) {
super(context, resource, objects);
this.context = context;
this.myList = objects;
}
#Override
public News getItem(int position) {
if(myList != null)
return myList.get(position);
return null;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null){
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_news, null);
holder = new NewsAdapter.Holder();
holder.title = (TextView)convertView.findViewById(R.id.textViewTitle);
holder.datePosted = (TextView)convertView.findViewById(R.id.textViewDate);
holder.imageView = (ImageView)convertView.findViewById(R.id.imageViewThumbnailpic);
convertView.setTag(holder);
}else{
holder = (Holder)convertView.getTag();
}
News news = getItem(position);
holder.title.setText(news.getTitle());
holder.datePosted.setText(news.getDatePost());
Picasso.with(context)
.load(news.getImgUrl())
.placeholder(R.drawable.coin25)
.error(R.drawable.hnbspic)
.into(holder.imageView);
return convertView;
}
private class Holder{
ImageView imageView;
TextView title;
TextView datePosted;
}
}
It's better to use Recyclerview because it has been optimized for various scenarios and not just for View holder pattern like it give the option for determining how your item should be laid out or like what should be the animation or custom drawing in each item.You can read more this medium post

Android ListView Show Wrong Position

I have a problem with ListView. Here the code of adapter :
public class AdapterListViewEncyclopedia extends ArrayAdapter<Apple> {
private int layoutResourceId;
private Context context;
private List<Apple> data;
private CellHolder holder;
public AdapterListViewEncyclopedia(Context context, int layoutResourceId, List<Apple> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
static class CellHolder
{
ImageView imageApple;
TextView tvCellAppleName;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new CellHolder();
holder.imageApple = (ImageView) row.findViewById(R.id.imageApple);
holder.tvCellAppleName = (TextView)row.findViewById(R.id.tvAppleName);
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(InterfaceConfig.serverURL+data.get(position).getImageURL(), holder.imageApple);
holder.tvCellAppleName.setText(data.get(position).getName());
System.out.println(position);
row.setTag(holder);
}
else
{
holder = (CellHolder)row.getTag();
}
return row;
}
}
The Main Problem :
1.I have 10 data in ArrayAdapter<Apple> and When i open page with ListView and i print position code with System.out.println, the code show 0,1,2,3,4,5,0
2. When i scroll the ListView , Top and Bottom which hidden is random position.
Anyone can help me to solve my problem?
I have update the code pls try this. You have to set the data after the if-else block other wise you cannot get the correct position in the listview while binding the data. Please refer the android view holder properties
ViewHolder
public class AdapterListViewEncyclopedia extends ArrayAdapter<Apple> {
private int layoutResourceId;
private Context context;
private List<Apple> data;
private CellHolder holder;
public AdapterListViewEncyclopedia(Context context, int layoutResourceId, List<Apple> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
static class CellHolder
{
ImageView imageApple;
TextView tvCellAppleName;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new CellHolder();
holder.imageApple = (ImageView) row.findViewById(R.id.imageApple);
holder.tvCellAppleName = (TextView)row.findViewById(R.id.tvAppleName);
row.setTag(holder);
}
else
{
holder = (CellHolder)row.getTag();
}
// you can set the data here
setData(position,holder);
return row;
}
private void setData(int position, CellHolder holder)
{
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(InterfaceConfig.serverURL+data.get(position).getImageURL(), holder.imageApple);
holder.tvCellAppleName.setText(data.get(position).getName());
}
}

Android - Images changing on GridView when scrolling

I am trying to create a custom adapter for a shop element in my Android app but every time I scroll down the list the images seem to change their position, I have had a look around on here already but suggestions that I have found and tried have been to no avail.
Each item has a title, an image (being loading via an AsyncTask or retrieved from the LRUCache) and a price of the item below is the code I use to generate the adapter.
public class ShopAdapter extends BaseAdapter {
public Context context;
public ArrayList<ShopItem> shopItemList;
public ImageCache imageCache;
String imageToLoad;
Bitmap shopImage;
public ShopAdapter(Context context, ArrayList<ShopItem> shopItemList) {
this.context = context;
this.shopItemList = shopItemList;
imageCache = new ImageCache(this.context);
}
#Override
public int getCount() {
return shopItemList.size();
}
#Override
public Object getItem(int position) {
return shopItemList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.shop_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.textView3);
holder.image =(ImageView) convertView.findViewById(R.id.imageView);
holder.price = (TextView) convertView.findViewById(R.id.textView4);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(shopItemList.get(position).getTitle());
shopImage = imageCache.getBitmapFromMemoryCache(shopItemList.get(position).getImage());
if(shopImage != null) {
holder.image.setImageBitmap(shopImage);
} else {
new LoadImage(context, holder.image).execute(imageToLoad);
}
holder.price.setText(shopItemList.get(position).getPrice());
return convertView;
}
static class ViewHolder {
TextView title;
ImageView image;
TextView price;
}
}
Any help would be very much appreciated!

Sliding menu adapter(android)

Sorry for my english. I use SlideMenu libruary and i want use new font for textview, it old version use:
((ListView) ((Activity) context).findViewById(R.id.sidemenulistobject)).setAdapter(
new ArrayAdapter<Object>(
context,
R.layout.sidemenu_item,
R.id.textSlide,
items
)
);
But this i cant get my textSlide and set new font. Now i add array adapter and set this in listView. This is my all code:
menu = new SlidingMenu(context);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
menu.setShadowWidth(15);
menu.setFadeDegree(1.0f);
menu.setShadowWidthRes(R.dimen.shadow_width);
menu.setShadowDrawable(R.drawable.shadow);
menu.attachToActivity((Activity) context, SlidingMenu.SLIDING_WINDOW);
menu.setBehindWidth(400);
menu.setMenu(R.layout.sidemenu);
//add item in list view
ArrayList<String> itemsObj = new ArrayList<String>();
itemsObj.add("Новости");
itemsObj.add("События");
itemsObj.add("Наше меню");
itemsObj.add("Фотографии");
itemsObj.add("Видеозаписи");
itemsObj.add("Контакты");
itemsObj.add("Мой профиль");
//get sidemenulistobject
ListView lv = ((ListView) ((Activity) context).findViewById(R.id.sidemenulistobject));
//add adapter
SlideAdapter adapter = new SlideAdapter((Activity) context, R.layout.sidemenu_item, itemsObj);
lv.setAdapter(adapter);
This is my SlideAdapter
public class SlideAdapter extends ArrayAdapter<MenuCategoryObject>{
ArrayList<String> listItems;
int Resourse;
Context context;
LayoutInflater vi;
private ImageLoader imageLoader;
public SlideAdapter(Context context, int resource, ArrayList<String> listItems) {
super(context, resource);
this.listItems = listItems;
Resourse = resource;
this.context = context;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = vi.inflate(Resourse, null);
holder = new ViewHolder();
Typeface face=Typeface.createFromAsset(context.getAssets(), "font/AvenirNext-Medium.ttf");
holder.textSlide = (TextView) convertView.findViewById(R.id.textSlide);
holder.textSlide.setTypeface(face);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textSlide.setText(listItems.get(position));
return convertView;
}
static class ViewHolder {
public TextView textSlide;
}
}
But my item list view dont show. I dont know why. Please help
the problem is with your adapter. Since you are not providing the dataset to the super constructor, you have to override getCount and return its size. Add
public int getCount() {
return listItems.size();
}
to your adapter

Adapters not output image(android)

Sorry for my english. I am using adapter, and I may be wrong somthing using it. I am trying to show image and textView as output. Textview is coming properly in the output, but image is not. Please help me, i try many many times fix it. Load image in DownloadImageTask. In DownloadImageTask i have class ImageLoader, i have used this tutorial. I don't have any error, i have nothing(
ArrayList<News> ArrayListNews;
int Resourse;
Context context;
LayoutInflater vi;
public NewsAdapter(Context context, int resource, ArrayList<News> objects) {
super(context, resource, objects);
ArrayListNews = objects;
Resourse = resource;
this.context = context;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = vi.inflate(Resourse, null);
holder = new ViewHolder();
holder.imageview = (ImageView) convertView.findViewById(R.id.imagenews);
holder.nameNews = (TextView) convertView.findViewById(R.id.namenews);
holder.dayNews = (TextView) convertView.findViewById(R.id.daynews);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
new DownloadImageTask(holder.imageview).execute(ArrayListNews.get(position).getImageNews());
holder.nameNews.setText(ArrayListNews.get(position).getNameNews());
holder.dayNews.setText(ArrayListNews.get(position).getDayNews());
return convertView;
}
static class ViewHolder {
public ImageView imageview;
public TextView nameNews;
public TextView dayNews;
}
//this is class set image
private class DownloadImageTask extends AsyncTask<String, Void, String> {
ImageView bmImage;
ImageLoader imgLoader;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
#Override
protected String doInBackground(String... urls) {
String urldisplay = urls[0];
return urldisplay;
}
protected void onPostExecute(String result) {
imgLoader = new ImageLoader(context.getApplicationContext());
imgLoader.DisplayImage(result, bmImage);
}
}
I will suggest you to use Picasso library. It is very easy to use. Just add dependency(Android Studio) or add .jar file into your library(in Eclipse).
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
That's it. Now you will not need AsyncTask to download images.
Your getView() will be
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = vi.inflate(Resourse, null);
holder = new ViewHolder();
holder.imageview = (ImageView) convertView.findViewById(R.id.imagenews);
holder.nameNews = (TextView) convertView.findViewById(R.id.namenews);
holder.dayNews = (TextView) convertView.findViewById(R.id.daynews);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// I am not sure about return value of ArrayListNews.get(position).getImageNews();
// It should be URL pointing to your image file
Picasso.with(context).load(ArrayListNews.get(position).getImageNews()).into(holder.imageview);
holder.nameNews.setText(ArrayListNews.get(position).getNameNews());
holder.dayNews.setText(ArrayListNews.get(position).getDayNews());
return convertView;
}

Categories

Resources