I use this code to download and set images from link to an image view
but when i scroll the list view and scroll back to top the images starts to download and clear the first downloaded picture.
I tried to download and save them into a array bitmap then show them but i cant update array bitmap like an array list and show it one by one in list view what can i do ?
class aa extends ArrayAdapter<String> {
public aa() {
super(MainActivity.this, R.layout.home_row, IDS);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater li = getLayoutInflater();
View row = li.inflate(R.layout.home_row, parent, false);
TextView name=(TextView)row.findViewById(R.id.home_row_name);
ImageView pic=(ImageView)row.findViewById(R.id.home_row_pic);
name.setText(arrayNAME.get(position).toString());
new Download_image(bitmap_PIC,position,pic).execute(PIC[position]);
return (row);
}
}
And here is the download method :
class Download_image extends AsyncTask<String, Void, Bitmap> {
Bitmap[] bitMap;
int position;
ImageView bmImage;
public Download_image(Bitmap[] bitMap,int position,ImageView bmImage) {
this.bitMap = bitMap;
this.position = position;
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) {
bitMap[position]=result;
bmImage.setImageBitmap(bitmap_PIC[position]);
}
}
Related
Iv tried some on the solutions in stack overflow, but was not able to work it out for my case.
I want to get the Bitmap data from onPostExecute or bmp from doInBackground and set it to ImageView imageurl using imageurl.setImageBitmap() in the getView() method
public class BooksAdapter extends ArrayAdapter<Books> {
public BooksAdapter(Activity context, ArrayList<Books> word) {
super(context, 0, word);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
// Get the {#link AndroidFlavor} object located at this position in the list
Books currentbook = getItem(position);
TextView bookView = (TextView) listItemView.findViewById(R.id.bookTittle);
String booktitle = currentbook.getBookName();
bookView.setText(booktitle);
TextView authorView = (TextView) listItemView.findViewById(R.id.authorname);
String authorname = currentbook.getAuthorName();
authorView.setText(authorname);
ImageView imageurl = (ImageView) listItemView.findViewById(R.id.imageView);
String imagelink = currentbook.getImageLink();
ImageAsyncTask task = new ImageAsyncTask();
task.execute(imagelink);
// imageurl.setImageBitmap();
return listItemView;
}
private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected Bitmap doInBackground(String... urls) {
URL url = null;
Bitmap bmp = null;
try {
url = new URL(urls[0]);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error with creating URL ", e);
}
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
}
return bmp;
}
#Override
protected void onPostExecute(Bitmap data) {
}
}
}
Just pass your ImageView to AsyncTask via constructor and then set image in onPostExecute like this:
ImageAsyncTask task = new ImageAsyncTask(myImageView);
private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView img;
ImageAsyncTask(Imageview img){
this.img = img;
}
...
protected void onPostExecute(Bitmap data) {
this.img.setImageBitmap(data);
}
The adapter provides data for a listview. But when you scroll up and down, it shows old images and takes a couple of seconds to finish loading the images. This is true when you open the view for the first time.
public class BooksAdapter extends ArrayAdapter<Books> {
public BooksAdapter(Activity context, ArrayList<Books> word) {
super(context, 0, word);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
// Get the {#link AndroidFlavor} object located at this position in the list
Books currentbook = getItem(position);
TextView bookView = (TextView) listItemView.findViewById(R.id.bookTittle);
String booktitle = currentbook.getBookName();
bookView.setText(booktitle);
TextView authorView = (TextView) listItemView.findViewById(R.id.authorname);
String authorname = currentbook.getAuthorName();
authorView.setText(authorname);
ImageView imageurl = (ImageView) listItemView.findViewById(R.id.imageView);
String imagelink = currentbook.getImageLink();
ImageAsyncTask task = new ImageAsyncTask(imageurl);
task.execute(imagelink);
return listItemView;
}
private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView img;
ImageAsyncTask(ImageView img) {
this.img = img;
}
#Override
protected Bitmap doInBackground(String... urls) {
URL url = null;
Bitmap bmp = null;
try {
url = new URL(urls[0]);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error with creating URL ", e);
}
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
}
return bmp;
}
#Override
protected void onPostExecute(Bitmap data) {
this.img.setImageBitmap(data);
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
}
I will recomend to use Glide for this task and dont invent bicycle. You can just call GlideApp.with(this).load("http://url.com").into(imageView); and Glide will do all work for you.
Glide with default image if actual image not loaded from the server.
Place this in app.gradle
compile 'com.github.bumptech.glide:glide:3.7.0'
Use it like,
Glide.with(this)
.load("your_image_url")
.listener(new RequestListener<String, GlideDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
e.printStackTrace();
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
Log.d("d", "onResourceReady");
return false;
}
})
.error("your_default_image")// placed in drawable
.into("your_target_view");
Hope this helps.
User Picasso best way to display image even you can set default image when image is loading see below example..
Picasso.with(context).load(imageUrl).placeholder(R.drawable.default_image).into(imageView);
compile 'com.squareup.picasso:picasso:2.4.0' just add into build.gradle
I have this image adapter, that is supposed to handle updating a grid of images. The problem is that I have a BackgroundImageTask running that fetches the bitmap from a URL. The getView method returns the imageView before the Background Task can finish updating it. How Can I force the Background Task to finish before it returns the imageview?
public class ImageAdapter extends BaseAdapter {
private Context mContext;
Bitmap bitmap;
List<Post> postList;
ImageView imageView;
int pos;
public ImageAdapter(Context c, List<Post> p) {
mContext = c;
postList = p;
}
public int getCount() {
return postList.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) {
pos=position;
View convert = convertView;
if (convert == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, 320));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 0, 0, 0);
} else {
imageView = (ImageView) convert;
}
new BackgroundImageTask().execute();
return imageView;
}
public View SetBit(Bitmap b){
imageView.setImageBitmap(b);
return imageView;
}
class BackgroundImageTask extends AsyncTask<Void, Void, Bitmap> {
#Override
protected Bitmap doInBackground(Void... params) {
Bitmap bit1=bitmap;
try {
bit1 = BitmapFactory.decodeStream((InputStream)new URL(postList.get(pos).thumbnail).getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bit1;
}
#Override
protected void onPostExecute(Bitmap bit) {
SetBit(bit);
}
}
}
Instead You can pass the ImageView Object to the background Task like
new BackgroundImageTask(imageView).execute();
and
class BackgroundImageTask extends AsyncTask<Void, Void, Bitmap> {
ImageView iv;
BackgroundImageTask(ImageView imageView){
iv = imageView;
}
#Override
protected Bitmap doInBackground(Void... params) {
Bitmap bit1=bitmap;
try {
bit1 = BitmapFactory.decodeStream((InputStream)new URL(postList.get(pos).thumbnail).getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bit1;
}
#Override
protected void onPostExecute(Bitmap bit) {
iv.setImageBitmap(bit);
}
}
My static list consists of images and data.I am loading images in background asynchronously.Still loading of images slows down scrolling performance.If i comment out the image loading code list scrolls very fast.How can i imporove scrolling performance while loading images in list?Below is the code i am using for loading images-
public View getView(final int i, View v, ViewGroup viewGroup) {
thumbnailImageView = (ImageView) view.findViewById(R.id.video_thumbnail);
final String id = video.getId();
String thumbnailPath = FileUtils.getCachedFileName(0,video.getId());
BitmapWorkerTask task = new BitmapWorkerTask(thumbnailImageView);
task2.execute(thumbnailPath);
.
.
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap>
{
private final ImageView imageViewReference;
public BitmapWorkerTask(ImageView imageView)
{
imageViewReference = imageView;
}
#Override
protected Bitmap doInBackground(String... urls) {
return BitmapFactory.decodeFile(urls[0]);
}
#Override
protected void onPostExecute(Bitmap bitmap)
{
imageViewReference.setImageBitmap(bitmap);
}
}
You could use Universal Image Library for loading the images in the background. It has a feature to stop loading the image onScroll or Fling.
Try Picasso as it has support for local files as well:
Picasso.with(context).load(R.drawable.landing_screen).into(imageView1);
Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2);
Picasso.with(context).load(new File(...)).into(imageView3);
Check the below code..It may help to you...You are not providing full code..So I assumed that you are extending your adapter from BaseAdapter and your list item is having one ImageView
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
LruCache<Integer, Bitmap> mMemoryCache = new LruCache<Integer, Bitmap>(
cacheSize) {
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
#Override
protected int sizeOf(Integer key, Bitmap bitmap) {
return bitmap.getByteCount() / 1024;
}
};
/**
* This will return a bitmap from the cache
*
* #param key
* #return
*/
public Bitmap getBitmapFromMemCache(Integer key) {
return mMemoryCache.get(key);
}
/**
* This method will add the bitmap to the memory cache
*
* #param key
* #param bitmap
*/
public void addBitmapToMemoryCache(Integer key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
private View video;
#Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder = null;
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.list_item,
null);
holder = new ViewHolder();
holder.thumbnailImageView = (ImageView) view
.findViewById(R.id.video_thumbnail);
view.setTag(holder);
}
else {
holder = (ViewHolder) view.getTag();
}
if (holder.bitmapWorkerTask!= null && holder.bitmapWorkerTask.getStatus() == Status.RUNNING) {
holder.bitmapWorkerTask.cancel(true);
}
Bitmap bitmapFromMemCache = getBitmapFromMemCache(position);
if (bitmapFromMemCache == null) {
holder.thumbnailImageView.setImageResource(R.drawable.default_image);
holder.bitmapWorkerTask = new BitmapWorkerTask(holder.thumbnailImageView,position);
String thumbnailPath = FileUtils.getCachedFileName(0, video.getId());
holder.bitmapWorkerTask.execute(thumbnailPath);
} else {
holder.thumbnailImageView.setImageBitmap(bitmapFromMemCache);
}
........
}
private class ViewHolder {
private ImageView thumbnailImageView;
private BitmapWorkerTask bitmapWorkerTask;
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final ImageView imageViewReference;
private int position;
public BitmapWorkerTask(ImageView imageView,int position) {
imageViewReference = imageView;
this.position=position;
}
#Override
protected Bitmap doInBackground(String... urls) {
Bitmap bitmap= BitmapFactory.decodeFile(urls[0]);
addBitmapToMemoryCache(position, bitmap);
return bitmap
}
#Override
protected void onPostExecute(Bitmap bitmap) {
imageViewReference.setImageBitmap(bitmap);
}
}
For some reason my custom adapter is only allowing me to have 1 image visible in the list view at any time, I am not sure why this is happening. There should be a image within each list item but only the last list item has its image set, so I assume I am re-using a value somewhere that I should not be. The rest of the list items are being set properly.
public class CustomAdapter extends ArrayAdapter<Item> {
private ArrayList<Item> itemList;
private ViewHolder holder;
private Context context;
public CustomAdapter(Context context, int textViewResourceId, ArrayList<Item> list) {
super(context, textViewResourceId, list);
this.itemList = new ArrayList<Item>();
this.itemList.addAll(list);
this.context = context;
}
private class ViewHolder {
ImageView img;
TextView name;
CheckBox access;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_grid, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.access = (CheckBox) convertView.findViewById(R.id.checkBox1);
holder.img = (ImageView) convertView.findViewById(R.id.imageView1);
convertView.setTag(holder);
}
else { holder = (ViewHolder) convertView.getTag(); }
Item it = itemList.get(position);
new UrlLookup().execute(it.getUrl());
holder.name.setText(it.getName());
holder.access.setChecked(it.isSelected());
return convertView;
}
//Create an image from the url passed in from the server and display it on the image view
private class UrlLookup extends AsyncTask<String, Integer, String>{
Bitmap bmp;
#Override
protected String doInBackground(String... params){
try {
URL u = new URL(params[0]);
bmp = BitmapFactory.decodeStream(u.openConnection().getInputStream());
} catch (Exception e) { e.printStackTrace(); }
return "Done!";
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
holder.img.setImageBitmap(bmp);
}
}
}
You're forgetting the fact that your holder changes every time a view is visible. So it's normal only the last item has an image.
AsyncTask will take considerably longer to finish than your getView method.
You should pass your ImageView to your AsyncTask:
new UrlLookup().execute(it.getUrl(), holder.img);
To call the AsyncTask
private class UrlLookup extends AsyncTask<Object, Integer, String>{
Bitmap bmp;
ImageView view;
#Override
protected String doInBackground(Object... params){
view = (ImageView) params[1];
try {
URL u = new URL((String)params[0]);
bmp = BitmapFactory.decodeStream(u.openConnection().getInputStream());
} catch (Exception e) { e.printStackTrace(); }
return "Done!";
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
view.setImageBitmap(bmp);
}
}
Now you will have a reference of the ImageView of every row in every AsyncTask.
I would like to point out to you that Koush has a splendid project for doing just what you want:
UrlImageViewHelper