I load images via Picasso Library in my custom adapter and then show it in my ListFragment. When I am trying to scroll, some of the images changes order (I think it is something wrong with reusing cells).
What is the best place to download images asynchronously? I do it in my custom adapter with viewholder.
public class PostsAdapter extends BaseAdapter {
private static final String TAG = "tag.example.tag";
private static final String URL_PREFIX = "http://someapi.com/v1/api/";
private Context mContext;
private ArrayList<Post> mData;
private static LayoutInflater inflater = null;
public PostsAdapter(Context context, ArrayList<Post> data) {
mContext = context;
mData = data;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
}
#Override
public boolean isEnabled(int position) {
return true;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int i) {
return i;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View v = view;
ViewHolder holder = null;
if(view == null)
v = inflater.inflate(R.layout.post_listviewrow, null);
holder = new ViewHolder();
holder.imageView = (ImageView) v.findViewById(R.id.imageView);
Post post = (Post) mData.get(i);
// Download image with Picasso
holder.imageView.setTag(post.getPictureUrl());
Picasso.with(mContext).load(URL_PREFIX + post.getPictureUrl()).into(holder.imageView);
return v;
}
static class ViewHolder {
TextView titleTextView;
ImageView imageView;
}
}
SOLUTION:
Changed getView method to something like this
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
if(view == null) {
view = inflater.inflate(R.layout.post_listviewrow, null);
holder = new ViewHolder();
holder.imageView = (ImageView) view.findViewById(R.id.imageView);
holder.titleTextView = (TextView) view.findViewById(R.id.textview);
holder.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Get position
Post post = (Post) mData.get(i);
holder.titleTextView.setText(post.getTitle());
Picasso picasso = Picasso.with(mContext);
picasso.setIndicatorsEnabled(true);
holder.progressBar.setVisibility(View.VISIBLE);
picasso.load(URL_PREFIX + post.getPictureUrl())
.placeholder(R.drawable.placeholder)
.fit()
.centerCrop()
.into(holder.imageView, new Callback() {
#Override
public void onSuccess() {
holder.progressBar.setVisibility(View.GONE);
}
#Override
public void onError() {}
});
return view;
}
static class ViewHolder {
TextView titleTextView;
ImageView imageView;
ProgressBar progressBar;
}
Anyway, Do you think the adapter is the right place to put download tasks?
Related
I have dynamically populated ImageViews and Textviews.
Now I have small problem with implementing onClick method on ImageView. On some ImageView click it should switch to fragment and for some click onto activity.
here is my code - my main fragment:
public class MainFragment extends Fragment {
public static String[] gridViewStrings = {
"string1",
"string2",
"string3",
"string4",
"string5",
"string6"
};
public static int[] gridViewImages = {
R.drawable.delivery,
R.drawable.shipping_logs,
R.drawable.meassurement,
R.drawable.takeovers,
R.drawable.settings,
R.drawable.download_data
};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main_fragment, parent, false);
gridView = (GridView) view.findViewById(R.id.grid);
gridView.setAdapter(new CustomAndroidGridViewAdapter(getActivity(), gridViewStrings, gridViewImages));
imageView = (ImageView) view.findViewById(R.id.gridview_image);
}
my custom gridview adapter:
public class CustomAndroidGridViewAdapter extends BaseAdapter {
private Context mContext;
private final String[] string;
private final int[] Imageid;
public CustomAndroidGridViewAdapter(Context c,String[] string,int[] Imageid ) {
mContext = c;
this.Imageid = Imageid;
this.string = string;
}
#Override
public int getCount() {
return string.length;
}
#Override
public Object getItem(int p) {
return null;
}
#Override
public long getItemId(int p) {
return 0;
}
#Override
public View getView(final int p, final View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.grid, null);
TextView textView = (TextView) grid.findViewById(R.id.gridview_text);
ImageView imageView = (ImageView)grid.findViewById(R.id.gridview_image);
textView.setText(string[p]);
imageView.setImageResource(Imageid[p]);
} else {
grid = (View) convertView;
}
return grid;
}
}
QUESTION: How to implement onClick() on ImageView and switch to fragment and activity?
public DlgOutletListAdapter(Context context, List<WrapperOutlet> wrapperOutletList, View.OnClickListener listener) {
this.context = context;
this.wrapperOutletList = wrapperOutletList;
this.listener = listener; //---> pass in listener....
}
#Override
public int getCount() {
return wrapperOutletList.size();
}
#Override
public Object getItem(int position) {
return wrapperOutletList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_dlg_outlet_list, parent, false);
viewHolder = new ViewHolder(convertView);
viewHolder.ll_dlg_outlet_list_container.setOnClickListener(listener);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
if (!wrapperOutletList.isEmpty()) {
WrapperOutlet wrapperOutlet = wrapperOutletList.get(position);
Outlet outlet = wrapperOutlet.getOutlet();
if (outlet != null) {
if (TextUtils.isEmpty(outlet.getTel())){
viewHolder.ivCall.setImageResource(R.drawable.icon_call2);
viewHolder.tvCall.setTextColor(context.getResources().getColorStateList(R.color.medium_gray));
viewHolder.ll_dlg_outlet_list_dialer.setOnClickListener(null);
} else {
viewHolder.ivCall.setImageResource(R.drawable.icon_call);
viewHolder.tvCall.setTextColor(context.getResources().getColorStateList(R.color.fresh_teal));
viewHolder.ll_dlg_outlet_list_dialer.setOnClickListener(listener);
}
}
}
return convertView;
}
Pass in listener. Give you an example above. code below is where you call the adapter in fragment. My fragment implements View.OnClickListener
lv_dlg_outlet_list.setAdapter(new DlgOutletListAdapter(activity, wrapperOutletList, this));
Interface Callback:
public interface LaunchFragmentWithImage{
void launchFragmentWithImage(int imageID);
}
Give the adapter a reference of this class below so it can call the method. Wouldn't recommend giving the adapter itself a reference to the class because its not the adapters responsibility to know who recieves the image, thus violating the Single responsibility principle of OOD, but for the sake of learning it's okay.
public class ClassToLaunchNewFragment extends AppCompatActivity implements
LaunchFragmentWithImage{
#Override //Method from interface we've defined.
public void launchFragmentWithImage(int imageID){
FragmentToLaunch fragmentToLaunch = FragmentToLaunch.newInstance();
Bundle imageData = new Bundle();
imageData.putInt(imageID, "key");
fragmentToLaunch.setArguments(imageData);
getSupportFragmentManager().beginTransaction() //Call replace not add
.replace(containerID, fragmentToLaunch)
.commit();
}
}
In AdapterClass
imageViewVar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
fragmentToLaunchInstanceThatWasPassedIn.launchFragmentWithImage(theImageResource);
}
});
grid = new View(mContext);
grid = inflater.inflate(R.layout.grid, null);
why are you pointing the grid variable to two separate View objects?
if (convertView == null) {
grid = inflater.inflate(R.layout.grid, null);
TextView textView = (TextView) grid.findViewById(R.id.gridview_text);
ImageView imageView = (ImageView)grid.findViewById(R.id.gridview_image);
textView.setText(string[p]);
imageView.setImageResource(Imageid[p]);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(choosedPosition){
case 0:do something;break;
case 1:do something;break;
...
}
}
});
}
It's just an example and can't running.
I'm fetching data using async task which has details of movies like ImageUrl, title, rating , e.t.c. I've generated a movie class for movie and I am loading the Images from ImageUrl in my gridView . Clicking on Image will navigate to that movie_detail_activity. Now when I run the app initially , clicking on image navigates to activity with correct details but when I scroll down and then up , imageViews get automatically changed but the Details activity remains as it was initially.
import...
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "https://api.themoviedb.org/3/movie/top_rated?api_key=MY_KEY";
new FetchPopularMoviesData().execute(url);
}
public void launch_activity(View view, MovieClass movie){
Intent intent= new Intent(this,MovieDetails.class);
Gson gson = new Gson();
String movieJson = gson.toJson(movie);
intent.putExtra("MovieJSON",movieJson);
startActivity(intent);
}
public class FetchPopularMoviesData extends AsyncTask<String, Void, ArrayList<MovieClass>> {
private Exception exception;
protected void onPreExecute() {
}
protected ArrayList<MovieClass> doInBackground(String... urls) {
ArrayList<MovieClass> movies = new ArrayList<>();
//code for fetching data from api
return movies;
}
protected void onPostExecute(final ArrayList<MovieClass> movies) {
if (movies == null) {
Log.e("After Parse Error", "No data found ,THERE WAS AN ERROR");
Toast.makeText(getApplicationContext(), "No working internet connection", Toast.LENGTH_LONG).show();
}
else {
for (int i = 0; i < movies.size(); i++) {
String title_name = movies.get(i).getTitle();
Log.i("INFO", title_name);
}
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new MovieAdapter(MainActivity.this, movies));
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
launch_activity(v, movies.get(position));
}
});
}
}
}
And here is the code for the adapter
public class MovieAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<MovieClass> movies;
public MovieAdapter(Context c,ArrayList<MovieClass> movies) {
mContext = c;
this.movies = movies;
}
public int getCount() {
return movies.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
Picasso.with(mContext)
.load(movies.get(position).getPoster())
.into(imageView);
imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
return imageView;
}
}
How do I keep ImageView in sync with the movie_details_activity content?
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
Picasso.with(mContext)
.load(movies.get(position).getPoster())
.into(imageView);
return imageView;
}
Check if this could work.
Use ViewHolder.
This will surely solve your issue.Hope it helps.
private MovieClass mItem;//declare globally
private ViewHolder holder;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
mItem = getItem(position);
holder = null;
if (convertView == null) {
convertView = inflater
.inflate(R.layout.row_fav_mem_list_item, null); //add imageview in this layout..
holder = new ViewHolder(); //declare this globally
holder.userPic = (ImageView) convertView
.findViewById(R.id.img_user_pic);
convertView.setTag(holder);
}
else
holder = (ViewHolder) convertView.getTag();
String imgURL = mItem.getPoster();
if (!TextUtils.isEmpty(imgURL)) {
imgLoader.load(imgURL).error(R.drawable.user_profile_image) //use default image if there is no image.
.placeholder(R.drawable.user_profile_image)
.into(holder.userPic);
} else
holder.userPic.setImageResource(R.drawable.user_profile_image);
return convertView;
}
public static class ViewHolder {
ImageView userPic;
}
#Override
public MovieClass getItem(int position) {
return movies.get(position);
}
In my layout I have one columnd of items for phones and up to 10 columns of items for tablets. I dont expirience any lags when I test it on my phone, but lags are noticable on tablet.
I wonder if following measure will make listview consume less resourses.
Generally I always have following line in my adapter:
holder.tvTitle.setText("some text")
If I will replace it by
if(!holder.title.equals(data.get(position).getTitle())){
holder.title = data.get(position).getTitle();
holder.tvTitle.setText(holder.title);
}
will i get any benefits?
To Load images I am using UniversalImageLoader
And there is my adapter
public class FragmentArtistAdapter extends BaseAdapter {
private List<ArtistsEntity> data;
private Context context;
private DisplayImageOptions options;
public FragmentArtistAdapter(Context activity, List<ArtistsEntity> data) {
this.data = data;
this.context = activity;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.artist_stub)
.showImageForEmptyUri(R.drawable.artist_stub)
.showImageOnFail(R.drawable.artist_stub).cacheInMemory(true)
.cacheOnDisk(true).considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565).build();
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
final ViewHolder holder;
// reuse views
if (rowView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
rowView = inflater.inflate(R.layout.fragment_artist_list_item,
parent, false);
// configure view holder
holder = new ViewHolder(
(TextView) rowView.findViewById(R.id.tv_name),
(TextView) rowView.findViewById(R.id.tv_view_count),
(TextView) rowView.findViewById(R.id.tv_like_count),
(ImageView) rowView.findViewById(R.id.im_photo), position,
(ProgressBar) rowView.findViewById(R.id.progressbar1),
(LinearLayout) rowView.findViewById(R.id.ll_favorite_box),
(ImageView) rowView
.findViewById(R.id.im_favorite_indicator));
Typeface fontTitle = Typeface.createFromAsset(inflater.getContext()
.getAssets(), "fonts/ubuntu_r.ttf");
holder.title.setTypeface(fontTitle);
Typeface fontArtist = Typeface.createFromAsset(inflater
.getContext().getAssets(), "fonts/ubuntu_l.ttf");
holder.title.setShadowLayer(2f, -1, 1, Color.LTGRAY);
holder.viewCount.setTypeface(fontArtist);
holder.likeCount.setTypeface(fontArtist);
holder.likeCount.setShadowLayer(2f, -1, 1, Color.LTGRAY);
holder.viewCount.setShadowLayer(2f, -1, 1, Color.LTGRAY);
rowView.setTag(holder);
} else
holder = (ViewHolder) rowView.getTag();
if(!holder.sTitle.equals(data.get(position).getName())){
holder.sTitle = data.get(position).getName();
holder.title.setText(holder.sTitle);
}
holder.title.setText(data.get(position).getName());
holder.viewCount.setText("" + data.get(position).getViewCount());
holder.likeCount.setText("" + data.get(position).getFavoriteCount());
String value = data.get(position).getImageUrl();
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(value, holder.photo, options,
new MySimpleImageLoaderListener(holder, value));
boolean fav = data.get(position).isFavorite();
if (fav != holder.favorite) {
if (fav) {
holder.llFavBox.setBackgroundColor(context.getResources()
.getColor(R.color.blue_text_chart_position));
holder.favIndicator
.setImageResource(R.drawable.star_unselected_icon);
holder.likeCount.setTextColor(context.getResources().getColor(
R.color.white_text_60));
} else {
holder.llFavBox.setBackgroundColor(context.getResources()
.getColor(R.color.white_with_blue));
holder.favIndicator
.setImageResource(R.drawable.star_selected_icon);
holder.likeCount.setTextColor(context.getResources().getColor(
R.color.black_text_60));
}
holder.favorite = fav;
}
return rowView;
}
public class MySimpleImageLoaderListener extends SimpleImageLoadingListener {
private final ViewHolder holder;
private final String value;
public MySimpleImageLoaderListener(ViewHolder holder, String value) {
this.holder = holder;
this.value = value;
}
#Override
public void onLoadingStarted(String imageUri, View view) {
holder.progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onLoadingFailed(String imageUri, View view,
FailReason failReason) {
holder.progressBar.setVisibility(View.GONE);
}
#Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
holder.progressBar.setVisibility(View.GONE);
}
}
private static class ViewHolder {
final TextView title;
final TextView viewCount;
final TextView likeCount;
final ImageView photo;
final ProgressBar progressBar;
final int position;
final LinearLayout llFavBox;
final ImageView favIndicator;
boolean favorite = false;
String sTitle= "";
private ViewHolder(TextView title, TextView viewCount,
TextView likeCount, ImageView photo, int position,
ProgressBar progressBar, LinearLayout llFavBox,
ImageView favIndicator) {
this.title = title;
this.viewCount = viewCount;
this.likeCount = likeCount;
this.photo = photo;
this.position = position;
this.progressBar = progressBar;
this.llFavBox = llFavBox;
this.favIndicator = favIndicator;
}
}
What can be done to make improvements?
Setting a text should not be any problem, so for clearer code, I'd drop that equals() check.
Things in your code that actually might be time consuming:
Creating Typefaces again and again -- move that out somewhere and reuse Typefaces.
getViewCount() and getFavoriteCount() -- we do not know what's that, might be complex database queries and might cost time.
Image loading is definitely time consuming but is hopefully done asynchronously.
I moved most object initialisation out of getView to adaptor constructor or outside adapter at all
I can't find a solution for my problem. I have a gridview with layouts. The layouts contains an imageview and a textview. What I need is to animate the imageview when I touch an item. How can I detect the on item keydown event in the gridview?
Here is my adapter:
public class GridViewAdapter extends BaseAdapter {
private ArrayList<SingleButton> buttons;
private MainActivity mainActivity;
public GridViewAdapter(MainActivity mainActivity) {
this.mainActivity = mainActivity;
this.buttons = new ArrayList<SingleButton>();
Resources res = mainActivity.getApplicationContext().getResources();
String[] temp = res.getStringArray(R.array.buttons);
int[] buttonImages = { R.drawable.pic1, R.drawable.pic2,
R.drawable.pic3, R.drawable.pic4, R.drawable.pic5,
R.drawable.pic6, R.drawable.pic7, R.drawable.pic8,
R.drawable.pic9 };
for (int count = 0; count < 9; ++count) {
this.buttons
.add(new SingleButton(buttonImages[count], temp[count]));
}
}
#Override
public int getCount() {
return this.buttons.size();
}
#Override
public Object getItem(int position) {
return this.buttons.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("ViewHolder")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;
if (row == null) {
LayoutInflater layoutInflater = (LayoutInflater) mainActivity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.single_button, parent, false);
holder = new ViewHolder(row);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
holder.buttonImage.setImageResource(buttons.get(position).image);
holder.buttonText.setText(buttons.get(position).buttonText);
return row;
}
class ViewHolder {
ImageView buttonImage;
TextView buttonText;
public ViewHolder(View v) {
this.buttonImage = (ImageView) v.findViewById(R.id.imageViewButton);
this.buttonText = (TextView) v.findViewById(R.id.textViewButton);
}
}
class SingleButton {
int image;
String buttonText;
SingleButton(int image, String buttonText) {
this.image = image;
this.buttonText = buttonText;
}
}
You need to add View.OnTouchListener to the parent view, in which your image is. Here parent view is your grid row.
It can be done via using setOnTouchListener(View.OnTouchListener). Below is code, you need to replace ViewHolder class with below code.
class ViewHolder implements View.OnTouchListener {
ImageView buttonImage;
TextView buttonText;
public ViewHolder(View v) {
this.buttonImage = (ImageView) v.findViewById(R.id.imageViewButton);
this.buttonText = (TextView) v.findViewById(R.id.textViewButton);
v.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
// Here you can put animation for your image view
// this.buttonImage is the target image view.
}
return true;
}
}
I'm using code to load photo list from gallery into custom horisontal listview. Listview scrolls not smoothly. I decide to put loading photo in to background. But now listview shows nothing. Could you please give me any help? After some discussion i've made some correction. But the result shows empty listview.
Main.java
public class Main extends Activity {
private HorizontalImageAdapter horizontalimageAdapter;
private HorizontalListView listview;
private Utilf utils;
private ArrayList<String> imagePaths = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_horizontal_list_view);
utils = new Utilf(this);
imagePaths = utils.getFilePaths();
listview = (HorizontalListView) findViewById(R.id.gallery);
horizontalimageAdapter = new HorizontalImageAdapter(this, imagePaths);
listview.setAdapter(horizontalimageAdapter);
}
}
HorizontalImageAdapter.java
public class HorizontalImageAdapter extends BaseAdapter {
private Activity context;
private static ImageView imageView;
private ArrayList<String> plotsImages;
private LayoutInflater l_Inflater;
public HorizontalImageAdapter(Activity context, ArrayList<String> plotsImages) {
this.context = context;
this.plotsImages = plotsImages;
l_Inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return plotsImages.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = l_Inflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (holder.imageView != null) {
new ImageDownloaderTask(holder.imageView).execute(plotsImages.get(position));
}
return convertView;
}
private static class ViewHolder {
ImageView imageView;
}
}
ImageDownloader.java
class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int imageWidth = 96;
public ImageDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = loadBitmap(params[0]);
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
// imageView.setImageDrawable(imageView.getContext().getResources().getDrawable(R.drawable.list_placeholder));
}
}
}
}
You cannot do that, because your imageview will be reused multiple times.
You need a way to check that once the asynctask is done loading the bitmap you're still are on the exact same row of the listview otherwise you will display images at random position while scrolling through the listview. To do so you can store the bitmap url as tag on the imageview and check that tag just before calling setImageBitmap(). If it matches you can display the bitmap, otherwise do nothing.
But like #HERO said why don't you use Picasso lib that will do this in an infinitly better way ;)
List item
Please check your getItem(int position) method. It is returning null. Instead you have to return the Object from the list for that position itself
getView() method
You are directly returning convertView. Instead take it in one separate variable like this code
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
viewHolder.image = (ImageView) rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}
// fill data
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
if (s.startsWith("Windows7") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
holder.image.setImageResource(R.drawable.no);
} else {
holder.image.setImageResource(R.drawable.ok);
}
return rowView;
}
code taken from this link