Hello I am using listview and display images from server into it.
But the problem is that all loaded images are displayed in last item one by one instead display on respective position.
please help me to display that images in respective position
public class Offer_adapter extends ArrayAdapter<String> {
Context context1;
String[] offer_title;
String[] offerimg1;
String[] mrp;
String[] offerprice;
String[] you_save;
String[] imgURLArray;
Bitmap bitmap;
ImageView offerimg;
int a;
LayoutInflater inflater1;
public Offer_adapter(Context context1, String[] offer_title, String[] offerimg1, String[] mrp, String[] you_save, String[] offerprice) {
super(context1, R.id.offer_list, offer_title);
this.context1 = context1;
this.offer_title = offer_title;
this.offerimg1 = offerimg1;
this.mrp = mrp;
this.offerprice = offerprice;
this.you_save = you_save;
}
private static class ViewHolder {
String offerimg;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
inflater1 = (LayoutInflater) context1.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater1.inflate(R.layout.offer_list, null);
viewHolder = new ViewHolder();
}
android.util.Log.v("abhi", "" + position);
imgURLArray = new String[position + 1];
for (int i = 0; i <= position; i++) {
android.util.Log.v("abhijit", "" + position);
imgURLArray[i] = "http://www.surun.co/preost/mod_offer/images/" + offerimg1[position];
android.util.Log.v("abhi", "" + imgURLArray[position]);
}
a=position;
viewHolder = (ViewHolder) convertView.getTag();
TextView offertitle = (TextView) convertView.findViewById(R.id.ofrtitle);
TextView offermrp = (TextView) convertView.findViewById(R.id.offeroriginal);
offermrp.setPaintFlags(offermrp.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
TextView offersave = (TextView) convertView.findViewById(R.id.saveoffer);
TextView ofrprice = (TextView) convertView.findViewById(R.id.priceoffer);
offerimg = (ImageView) convertView.findViewById(R.id.ofr_img);
offertitle.setText(offer_title[position]);
offermrp.setText("Original Price: \u20B9" + mrp[position]);
offersave.setText("You Save: \u20B9" + you_save[position]);
ofrprice.setText("Offer Price: \u20B9" + offerprice[position]);
// Bitmap imageBitmap = null;
new DownloadAsyncTask().execute(imgURLArray[position]);
Log.v("abhi","async");
return convertView;
}
private class DownloadAsyncTask extends AsyncTask<String, String, Bitmap> {
protected Bitmap doInBackground(String... args) {
try {
Log.v("abhi","in do background");
bitmap = BitmapFactory.decodeStream((InputStream) new URL(args[0]).getContent());
bitmap = Bitmap.createScaledBitmap(bitmap, 270, 375, true);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap !=null) {
offerimg.setImageBitmap(bitmap);
} else {
offerimg.setImageResource(R.drawable.nooffer);
}
}
}
}
All images are shown in last item one after another. I just want to show it on respective position.
you should use lazyloading instead of downloading image as bitmap.
Bitmap will create problem sometime or will give you outofmemory error in some devices
There are lots of image loading library available for android.
Have a look at these
https://github.com/square/picasso
https://github.com/nostra13/Android-Universal-Image-Loader
https://code.google.com/p/android-query/wiki/ImageLoading
https://android.googlesource.com/platform/frameworks/volley
https://github.com/koush/UrlImageViewHelper
https://github.com/novoda/image-loader
Related
When I display album art directly in my music app, it hangs. In stackoverflow, someone suggested me to implemented AsyncTask. So, I implemented AsyncTask to make my app faster. Right now, my app is not hanging but it is not displaying correct album art. And album arts are random means changing frequently when I scroll my listview.
Please help me.
Here is AsyncTask class :
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
private long l;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
public BitmapWorkerTask(ImageView imageView, long l) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
this.l = l;
}
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
//Bitmap art = getAlbumart(songlist.this, l);
Context context = songlist.this;
Bitmap bm = null;
BitmapFactory.Options options = new BitmapFactory.Options();
try {
final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(sArtworkUri, l);
ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd, null, options);
pfd = null;
fd = null;
}
} catch (Error ee) {
} catch (Exception e) {
}
return bm;
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (bitmap != null) {
iv_art.setImageBitmap(bitmap);
} else {
iv_art.setImageResource(R.mipmap.app_splash_screen_icon);
}
}
}
}
My class which displays song in the listview :
public class MediaCursorAdapter extends SimpleCursorAdapter {
String backgroundColor = "white";
String someOtherBackgroundColor = "#FAFAFA";
public MediaCursorAdapter(Context context, int layout, Cursor c) {
super(context, layout, c,
new String[]{MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.TITLE, MediaStore.Audio.AudioColumns.DURATION, MediaStore.Audio.Media.ALBUM_ID},
new int[]{R.id.displayname, R.id.title, R.id.duration, R.id.iv_art});
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
if (cursor.getPosition() % 2 == 0) {
view.setBackgroundColor(
Color.parseColor(backgroundColor));
} else {
view.setBackgroundColor(
Color.parseColor(someOtherBackgroundColor));
}
TextView title = (TextView) view.findViewById(R.id.title);
TextView name = (TextView) view.findViewById(R.id.displayname);
TextView duration = (TextView) view.findViewById(R.id.duration);
iv_art = (ImageView) view.findViewById(R.id.iv_art);
String a = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
l = Long.parseLong(a);
bwc = new BitmapWorkerTask(iv_art,l);
bwc.execute();
long durationInMs = Long.parseLong(cursor.getString(
cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION)));
name.setText(cursor.getString(
cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)));
title.setText(cursor.getString(
cursor.getColumnIndex(MediaStore.MediaColumns.TITLE)));
Utility d = new Utility();
String durationInMin = d.convertDuration(durationInMs);
duration.setText("" + durationInMin);
view.setTag(cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.songlist_listitem, parent, false);
bindView(v, context, cursor);
return v;
}
}
Its because of row reordering. The image view you want to load it into when you start a fetch is not necessarily where you want to load it at the end. The weak reference isn't helping because the view isn't being destroyed, its just not the right one anymore.
Instead of loading the data directly into the view, store it in a cache, then call notifyDataSetChanged. When you bind the row, check and see if the image is int he cache. If so, use it. If not, send the request. That will fix the majority of the issues you see, and prevent OOM errors (you can put a max memory usage on the cache).
Or use a library that does all this for you, like Volley.
how do i display image using the imagepath fetched from mysql database into gridview. i tried lot but unable to do.
this is my asynctask code:
public class sampling_info extends AsyncTask<String, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SamplingActivity.this);
pDialog.setMessage("Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
String doc = dcname.toString();
ArrayList<NameValuePair> namevaluepair = new ArrayList<NameValuePair>();
namevaluepair.add(new BasicNameValuePair("docname", doc));
JSONObject json = jParser.makeHttpRequest(URL_SAMPLING, "POST",
namevaluepair);
return json;
}
protected void onPostExecute(JSONObject json) {
// dismiss the dialog once done
pDialog.dismiss();
if (json != null) {
try {
JSONArray jarray = json.getJSONArray("product_entered");
Log.d("jarray in sampling : ", "" + jarray.toString());
for (int i = 0; i < jarray.length(); i++) {
JSONObject jobj = jarray.getJSONObject(i);
String docname = jobj.getString("docname");
String imagep= jobj.getString("image_path");
GridItem gItem= new GridItem();
gItem.setTitle("sagar");
gItem.setImage(imagep);
mgrid.add(gItem);
Log.d("jobj : ", "" + jobj);
Log.d("jobj docname", "" + docname);
}
} catch (Exception e) {
e.printStackTrace();
}
gridAdapter = new GridViewAdapter(SamplingActivity.this, R.layout.grid_item_layout,mgrid);
gridview.setAdapter(gridAdapter);
}
}
i this asynctask am fetching imagepath from database and storing it in imagep variable and passing it to GridItem class
This is my griditem class :
public class GridItem {
private Bitmap image;
private String title,image1;
public GridItem(Bitmap image) {
this.image=image;
}
public Bitmap getImage() {
return image;
}
public Bitmap setImage(String image) { // this is where am trying to set my image but can't do.
try {
} catch (Exception e) {
}
return null;
}
And this is my adapter class :
public GridViewAdapter(Context mContext, int layoutResourceId,
ArrayList<GridItem> mGridData) {
super(mContext, layoutResourceId, mGridData);
this.layoutResourceId = layoutResourceId;
this.mContext = mContext;
this.mGridData = mGridData;
}
/**
* Updates grid data and refresh grid items.
*
* #param mGridData
*/
public void setGridData(ArrayList<GridItem> mGridData) {
this.mGridData = mGridData;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
//ViewHolder holder;
ImageView imageView = (ImageView) row
.findViewById(R.id.grid_item_image);
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
// holder = new ViewHolder();
//imageView = (ImageView) convertView;
TextView titleTextView = (TextView) row
.findViewById(R.id.grid_item_title);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
}
GridItem item = mGridData.get(position);
imageView.setImageBitmap(item.getImage());
return row;
}
I suggest you to use Universal Image Loader
First of all, include last version of jar file from 'lib' directory to your project
in Adapter :
ImageLoader imageLoader = null;
DisplayImageOptions options;
in Adapter's Contractor :
imageLoader = ImageLoader.getInstance();
options = new DisplayImageOptions.Builder()
/*.displayer(new RoundedBitmapDisplayer((int) 27.5f))*/
.showImageOnLoading(R.drawable.thumb_square)
.showImageForEmptyUri(R.drawable.thumb_square)
.showImageOnFail(R.drawable.thumb_square)
.cacheInMemory(true)
.cacheOnDisc(true)
.considerExifParams(true)
.imageScaleType(ImageScaleType.NONE)
.bitmapConfig(Bitmap.Config.RGB_565)
/*.postProcessor(new BitmapProcessor() {
#Override
public Bitmap process(Bitmap bitmap) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
float r = ((float)h / (float)w);
ExceptionHelpers.dLog("POST_PROCESSOR", "width : " + w + " , height : " + h + " , R1 : " + r + " , W : " + UIHelpers.width + " , Percent W : " + UIHelpers.setPercentW(r));
return Bitmap.createScaledBitmap(bitmap, UIHelpers.width, UIHelpers.setPercentW(r), false);
}
})*/
.build();
and getView :
String imgURL = "http://www.website.com/images/image_path.png";
imageLoader.init(ImageLoaderConfiguration.createDefault(mContext));
imageLoader.displayImage(imgURL, holder.img_view, options);
First of all dont store the bitmap in modelClass, Alternatively you can add sd card path or live url of an image(http://...)
Loading the image:
-- I suggest you to use Glide library
Code sample:
Glide.with(context)
.load(url) // pass your image url
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.crossFade() //animate the image
.into(myImageView);
After I decided to implement Universal Image Loader, because I had implemented a method that convert URL to Drawable, but since I don't know how many images it will return my SQLite query I decided to implement an Image Loader...
The thing is I'm stuck at the moment, cause I thought I did all what the GitHub say but at the time I load the Image it stays white and never loads.
On my Adapter class I've changed the line of the drawable as :
Picasso.with(context)
.load(Uri.parse(String.valueOf(item.icon)))
.resize(180, 180)
.placeholder(R.drawable.ic_launcher).into(viewHolder.ivIcon);
It works, beucase it shows yo me the ic_launcher icon... but never changes to the real image.
On my class where I fetch the data I have this (on my OnCreate()) :
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new MyAsyncTask().execute();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// progress.dismiss();
}
});
}
}).start();
}
Then I created an inner class where I fetch the data into my ListView... but it doesn't works. I don't know If I've to delte those methods since I've changed it to Picasso.
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
Conexion = new MarketSQLite(getActivity(), "market", null, 1);
mItems = new ArrayList<ListViewItem>();
db = Conexion.getReadableDatabase();
Cursor c;
c = db.rawQuery("Select NOM_OFER,PREU_OFERTA,DATA_F,FOTO,PERCENTDESCOMPTE from T_OFERTA", null);
c.moveToFirst();
if (c != null) {
do {
for (int i = 0; i < c.getColumnCount(); i++) {
Title = c.getString((c.getColumnIndex("NOM_OFER")));
Preu = c.getColumnIndex("PREU_OFERTA");
percent = c.getString((c.getColumnIndex("PERCENTDESCOMPTE")));
data_f = c.getString((c.getColumnIndex("DATA_F")));
URLTest = c.getString((c.getColumnIndex("FOTO")));
FOTO = Imagehandler(URLTest);
Log.e("", "" + c.getString(i));
// initialize and set the list adapter
// Toast.makeText(getActivity(), "Title" + Title + "Preu" + Preu + "Percent" + percent + "Cheese is " + data_f, Toast.LENGTH_LONG).show();
}
mItems.add(new ListViewItem(FOTO, Title, Preu.toString(), percent, data_f));
}while (c.moveToNext());
}
c.close();
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
myAdapter = new ListViewDemoAdapter(getActivity(), mItems);
setListAdapter(myAdapter);
}
}
Where ImageHandler is a method that I've created before this is :
protected Drawable Imagehandler(String url) {
try {
url=url.replaceAll(" ", "%20");
InputStream is = (InputStream)this.fetch(url);
Drawable d = Drawable.createFromStream(is, "src");
return d;
} catch (MalformedURLException e)
{
System.out.println(url);
System.out.println("error at URI"+e);
return null;
}
catch (IOException e)
{
System.out.println("io exception: "+e);
System.out.println("Image NOT FOUND");
return null;
}
}
protected Object fetch(String address) throws MalformedURLException,IOException {
URL url = new URL(address);
Object content = url.getContent();
return content;
}
I don't know why isn't the image loading on my ListView if it shows all of the rest of data...
Instead of Drawable, try to get url string in your adapter like
Change From
public ListViewItem(Drawable icon, String title, String precio, String descuento, String date) {
this.icon = icon;
this.title = title;
this.precio = precio;
this.descuento = descuento;
this.date = date;
}
To
public ListViewItem(String icon_url, String title, String precio, String descuento, String date) {
this.icon_url = icon_url;
this.title = title;
this.precio = precio;
this.descuento = descuento;
this.date = date;
}
and use Picasso where you are loading your imageview like this -
Picasso.with(context)
.load(icon_url))
.resize(180, 180)
.placeholder(R.drawable.ic_launcher).into(viewHolder.ivIcon);
1) Your ListViewItem class should be like this -
public class ListViewItem {
public final String icon; // the drawable for the ListView item ImageView
public final String title; // the text for the ListView item title
public final String precio; // the price for the ListView item
public final String descuento; // the price for the discount for the ListView item
public final String date; //the date for the sale for the ListView item
// the text for the ListView item description
public ListViewItem(String icon_url, String title, String precio, String descuento, String date) {
this.icon = icon_url;
this.title = title;
this.precio = precio;
this.descuento = descuento;
this.date = date;
}
}
2) ListViewDemoAdapterClass
public class ListViewDemoAdapter extends ArrayAdapter<ListViewItem> {
Context context;
public ListViewDemoAdapter(Context context, List<ListViewItem> items) {
super(context, R.layout.listview_item, items);
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null) {
// inflate the GridView item layout
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.listview_item, parent, false);
// initialize the view holder
viewHolder = new ViewHolder();
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
viewHolder.tvPrice = (TextView) convertView.findViewById(R.id.tvPrice);
viewHolder.tvDiscount = (TextView) convertView.findViewById(R.id.tvDiscount);
viewHolder.tvDate = (TextView) convertView.findViewById(R.id.tvDatas);
convertView.setTag(viewHolder);
} else {
// recycle the already inflated view
viewHolder = (ViewHolder) convertView.getTag();
}
// update the item view
ListViewItem item = getItem(position);
Picasso.with(context)
.load(item.icon)
.resize(180, 180)
.placeholder(R.drawable.ic_launcher).into(viewHolder.ivIcon);
viewHolder.tvTitle.setText(item.title);
viewHolder.tvDiscount.setText(item.descuento);
viewHolder.tvPrice.setText(item.precio);
viewHolder.tvDate.setText(item.date);
return convertView;
}
private static class ViewHolder {
ImageView ivIcon;
TextView tvTitle;
TextView tvDiscount;
TextView tvPrice;
TextView tvDate;
}
}
ListFragment code, just add this
Cursor c;
c = db.rawQuery("Select
NOM_OFER,PREU_OFERTA,DATA_F,FOTO,PERCENTDESCOMPTE from T_OFERTA", null);
c.moveToFirst();
if (c != null) {
do {
for (int i = 0; i < c.getColumnCount(); i++) {
Title = c.getString((c.getColumnIndex("NOM_OFER")));
Preu = c.getColumnIndex("PREU_OFERTA");
percent = c.getString((c.getColumnIndex("PERCENTDESCOMPTE")));
data_f = c.getString((c.getColumnIndex("DATA_F")));
URLTest = c.getString((c.getColumnIndex("FOTO")));
Hope this helps :)
you just need to add your picasso code snippet as the following in your ImageHandler method and nothing else-
Picasso.with(context)
.load(url))
.resize(180, 180)
.placeholder(R.drawable.ic_launcher).into(your_imageview);
you don't need to download the image or make the bitmap or convert that into drawable to load from url. hope this helps you.
I know that this question is asked many times.. But I cant get any proper solution, In my app I use AsyncTask for loading a image. I use AsyncTask because I want smooth scrolling listview.. and after implement AsyncTask My listView get smoothly scrolling.. But now problem is that Image is changing after scrolling... What should I do?
MyAdapter Class
package com.example.adapter;
public class DisplayAllFeedAdapter extends ArrayAdapter<DisplayAllFeedItem> {
private final List<DisplayAllFeedItem> list;
private final Activity context;
ExifInterface exif;
public DisplayAllFeedAdapter(Activity context, List<DisplayAllFeedItem> list) {
super(context, R.layout.feed_screen, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
public TextView optionalDesc, reportedBy;
public LinearLayout layout;
public ImageView displayFeedimg, channelIcon;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.display_all_feed_listitem, null);
viewHolder = new ViewHolder();
viewHolder.optionalDesc = (TextView) convertView.findViewById(R.id.txtFeedOptionalDesc);
viewHolder.reportedBy = (TextView) convertView.findViewById(R.id.txtFeedReportedBy);
viewHolder.displayFeedimg = (ImageView) convertView
.findViewById(R.id.imgFeedDisplayImage);
viewHolder.layout = (LinearLayout) convertView.findViewById(R.id.layoutChannelImgView);
convertView.setTag(viewHolder);
convertView.setTag(R.id.txtFeedOptionalDesc, viewHolder.optionalDesc);
convertView.setTag(R.id.txtFeedReportedBy, viewHolder.reportedBy);
convertView.setTag(R.id.imgFeedDisplayImage, viewHolder.displayFeedimg);
convertView.setTag(R.id.layoutChannelImgView, viewHolder.layout);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
String temp;
String drawableImagePath = list.get(position).getMediaChannelName();
List<String> channelList = new ArrayList<String>();
while (drawableImagePath.length() > 0) {
if (drawableImagePath.indexOf(",") == -1) {
temp = drawableImagePath.substring(0);
channelList.add(temp);
break;
} else {
temp = drawableImagePath.substring(0, drawableImagePath.indexOf(","));
}
channelList.add(temp);
drawableImagePath = drawableImagePath.substring(drawableImagePath.indexOf(",") + 1);
}
viewHolder.layout.removeAllViews();
for (int i = 0; i < channelList.size(); i++) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(dpToPx(30),
dpToPx(30));
ImageView imageView = new ImageView(context);
layoutParams.setMargins(0, 0, 10, 0);
imageView.setLayoutParams(layoutParams);
imageView.setImageResource(Integer.parseInt(channelList.get(i)));
viewHolder.layout.addView(imageView);
}
String tempPath = list.get(position).getMediaPath();
File mediaFile = new File(tempPath);
Bitmap bitmap;
viewHolder.optionalDesc.setText(list.get(position).getMediaDesc());
viewHolder.reportedBy.setText("Reported By " + list.get(position).getMediaDisplayName());
if (viewHolder != null) {
new LoadImage(viewHolder).execute(tempPath);
}
return convertView;
}
private class LoadImage extends AsyncTask<String, String, Bitmap> {
// File mediaFile = new File(tempPath);
Bitmap bitmap, displayBitmap;
File mediaFile;
String mediaPath;
private final ViewHolder imageViewReference;
public LoadImage(ViewHolder viewHolder) {
imageViewReference = viewHolder;
}
#Override
protected Bitmap doInBackground(String... params) {
// File f = new File(params[0]);
mediaPath = params[0];
mediaFile = new File(mediaPath);
if (mediaFile.exists()) {
if (isImage(mediaPath)) {
Bitmap myBitmap = BitmapFactory.decodeFile(mediaFile.getAbsolutePath());
int height = (myBitmap.getHeight() * 512 / myBitmap.getWidth());
Bitmap scale = Bitmap.createScaledBitmap(myBitmap, 512, height, true);
int rotate = 0;
try {
exif = new ExifInterface(mediaFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
rotate = 0;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
displayBitmap = Bitmap.createBitmap(scale, 0, 0, scale.getWidth(),
scale.getHeight(), matrix, true);
} else {
displayBitmap = ThumbnailUtils.createVideoThumbnail(mediaPath,
Thumbnails.MICRO_KIND);
}
}
return displayBitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (imageViewReference != null) {
imageViewReference.displayFeedimg.setImageBitmap(result);
}
// tempView.displayFeedimg.setImageBitmap(result);
}
}
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
public static boolean isImage(String str) {
boolean temp = false;
String[] arr = { ".jpeg", ".jpg", ".png", ".bmp", ".gif" };
for (int i = 0; i < arr.length; i++) {
temp = str.endsWith(arr[i]);
if (temp) {
break;
}
}
return temp;
}
}
I am not clear on your problem (need better clarification) but I know there are issues on loading images about the lag in performance.
Please Look at Google's web Making a Standard Request.
Search for (Universal) Image Loader, text "Use ImageLoader and NetworkImageView".
You can further improve performance by caching, located below that text.
Code snippet from the webpage:
ImageLoader mImageLoader;
ImageView mImageView;
// The URL for the image that is being loaded.
private static final String IMAGE_URL =
"http://developer.android.com/images/training/system-ui.png";
...
mImageView = (ImageView) findViewById(R.id.regularImageView);
// Get the ImageLoader through your singleton class.
mImageLoader = MySingleton.getInstance(this).getImageLoader();
mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
R.drawable.def_image, R.drawable.err_image));
There seems a good tutorial in Solving the Android image loading problem... by a knowledgeable author.
Have fun with this. And someday I may have to solve this problem as well. Pls keep us posted.
Besides my previous answer, there is another possible solution. But it is somewhat different than Google's recommendation, so beware...
Look at Stackoverflow discussion ListView like in universal image loader sample app. Checkout code in that page. In CarListAdapter:
ImageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
...In another method:
imageLoader.displayImage(...);
Both of my answers lead to one point, use the (Universal) Image Loader.
Here is how I set up the list view and how I get the image by downloading it.
Some variable explanation :
The PostItem is the model object that contain the data for a listview item
The ImageLoader is the async task class to download the image by getting the image url from PostItem
The problem are , the ordering of the image in the listview is incorrect , for example, the image should appear in 1st is appear in both 1st , 4th, and if I scroll , the display pattern change as well.
Also, I find the image are download again if I scroll, even I have check the imageView whether has drawable
Thanks for helping.
====================================================
Here is how I generate the listview:
static class ViewHolderItem {
TextView name;
TextView date;
ImageView img;
TextView msg;
TextView count;
ImageView likeBtn;
ImageView commentBtn;
ImageView shareBtn;
}
private class MyPostAdapter extends ArrayAdapter<PostItem> {
#Override
public boolean isEnabled(int position) {
return false;
}
public MyPostAdapter(Context context, int resource, List<PostItem> items) {
super(context, resource, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolderItem viewHolder;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.post_item, parent, false);
viewHolder = new ViewHolderItem();
viewHolder.name = (TextView) v.findViewById(R.id.postName);
viewHolder.date = (TextView) v.findViewById(R.id.postDate);
viewHolder.img = (ImageView) v.findViewById(R.id.postImg);
viewHolder.msg = (TextView) v.findViewById(R.id.postMsg);
viewHolder.count = (TextView) v.findViewById(R.id.count);
viewHolder.likeBtn = (ImageView) v.findViewById(R.id.likeBtn);
viewHolder.commentBtn = (ImageView) v.findViewById(R.id.commentBtn);
viewHolder.shareBtn = (ImageView) v.findViewById(R.id.shareBtn);
v.setTag(viewHolder);
} else {
viewHolder = (ViewHolderItem) convertView.getTag();
}
final PostItem post = getItem(position);
if (post != null) {
viewHolder.name.setText(post.name);
try {
c.setTime(sdf.parse(post.createDate));
} catch (ParseException e) {
e.printStackTrace();
}
relative_date = DateUtils.getRelativeDateTimeString (ctx, c.getTimeInMillis() , DateUtils.MINUTE_IN_MILLIS,DateUtils.WEEK_IN_MILLIS, 0).toString();
viewHolder.date.setText(relative_date);
viewHolder.msg.setText(post.txtMsg);
viewHolder.count.setText(post.likeCount + " " + getString(R.string.pro_like) + " " + post.commentCount + " " + getString(R.string.reply));
if (post.isLike) {
viewHolder.likeBtn.setImageResource(R.drawable.like);
} else {
viewHolder.likeBtn.setImageResource(R.drawable.before_like);
}
if (!post.imageURL.equals("null") && viewHolder.img.getDrawable() == null ) {
new ImageLoader(ctx).execute(viewHolder.img,Constant.comment_imageFolder + post.imageURL);
} else {
viewHolder.img.setImageDrawable(null);
}
viewHolder.likeBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new APIManager("like", ctx, Constant.likeAPI + "/"
+ post.commentID + "/" + userID, jsonListener,
getResources().getString(R.string.update_data));
}
});
viewHolder.commentBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<PostItem> filterReplyList = new ArrayList<PostItem>();
Intent i = new Intent(ctx, ReplyActivity.class);
i.putExtra("commentID", post.commentID);
// get reply list
for (PostItem reply : replyItemList) {
if (reply.postID.equals(post.commentID)
|| reply.commentID.equals(post.commentID)) {
filterReplyList.add(reply);
}
}
i.putExtra("replyItemList", filterReplyList);
startActivityForResult(i, 0);
}
});
viewHolder.shareBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
String data = "date: " + post.createDate + "\nmsg:" + post.txtMsg;
sendIntent.putExtra(Intent.EXTRA_TEXT, data);
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
});
}
return v;
}
}
And Here is the imageloader, take the imageview, url as input and put the bitmap in the imageview
public class ImageLoader extends AsyncTask<Object, Void, Bitmap> {
private static String TAG = "ImageLoader";
private InputStream input;
private ImageView view;
private ProgressBar loadingIcon;
private ListView myListView;
private String imageURL;
private Context ctx;
public ImageLoader(Context _ctx) {
ctx = _ctx;
}
#Override
protected Bitmap doInBackground(Object... params) {
try {
view = (ImageView) params[0];
// handle Chinese characters in file name
// String[] imgUrlArray = ((String) params[1]).split("/");
// String fileName = imgUrlArray[imgUrlArray.length - 1];
// String newfileName = URLEncoder.encode(fileName, "utf-8");
// imageURL = ((String) params[1]).replace(fileName, newfileName);
imageURL = ((String) params[1]);
if (params.length > 2 && (ProgressBar) params[2] != null)
loadingIcon = (ProgressBar) params[2];
URL url = new URL(imageURL);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
input = connection.getInputStream();
final BitmapFactory.Options options = new BitmapFactory.Options();
BufferedInputStream bis = new BufferedInputStream(input, 4*1024);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte)current);
}
byte[] imageData = baf.toByteArray();
BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
options.inJustDecodeBounds = true;
options.inSampleSize = 2;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if (input != null)
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
protected void onPostExecute(Bitmap result) {
if (result != null && view != null) {
if (loadingIcon != null)
loadingIcon.setVisibility(View.GONE);
view.setVisibility(View.VISIBLE);
view.setImageBitmap(result);
}
}
Updated code (implement volley library):
static class ViewHolderItem {
TextView name;
TextView date;
NetworkImageView img;
TextView msg;
TextView count;
ImageView likeBtn;
ImageView commentBtn;
ImageView shareBtn;
}
private class MyPostAdapter extends ArrayAdapter<PostItem> {
#Override
public boolean isEnabled(int position) {
return false;
}
public MyPostAdapter(Context context, int resource, List<PostItem> items) {
super(context, resource, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolderItem viewHolder;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.post_item, parent, false);
viewHolder = new ViewHolderItem();
viewHolder.name = (TextView) v.findViewById(R.id.postName);
viewHolder.date = (TextView) v.findViewById(R.id.postDate);
viewHolder.img = (NetworkImageView) v.findViewById(R.id.postImg);
viewHolder.msg = (TextView) v.findViewById(R.id.postMsg);
viewHolder.count = (TextView) v.findViewById(R.id.count);
viewHolder.likeBtn = (ImageView) v.findViewById(R.id.likeBtn);
viewHolder.commentBtn = (ImageView) v.findViewById(R.id.commentBtn);
viewHolder.shareBtn = (ImageView) v.findViewById(R.id.shareBtn);
v.setTag(viewHolder);
} else {
viewHolder = (ViewHolderItem) convertView.getTag();
}
final PostItem post = getItem(position);
if (post != null) {
viewHolder.name.setText(post.name);
try {
c.setTime(sdf.parse(post.createDate));
} catch (ParseException e) {
e.printStackTrace();
}
relative_date = DateUtils.getRelativeDateTimeString (ctx, c.getTimeInMillis() , DateUtils.MINUTE_IN_MILLIS,DateUtils.WEEK_IN_MILLIS, 0).toString();
viewHolder.date.setText(relative_date);
viewHolder.msg.setText(post.txtMsg);
viewHolder.count.setText(post.likeCount + " " + getString(R.string.pro_like) + " " + post.commentCount + " " + getString(R.string.reply));
if (post.isLike) {
viewHolder.likeBtn.setImageResource(R.drawable.like);
} else {
viewHolder.likeBtn.setImageResource(R.drawable.before_like);
}
if (!post.imageURL.equals("null")) {
viewHolder.img.setImageUrl(Constant.comment_imageFolder + post.imageURL, mImageLoader);
}
viewHolder.likeBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new APIManager("like", ctx, Constant.likeAPI + "/"
+ post.commentID + "/" + userID, jsonListener,
getResources().getString(R.string.update_data));
}
});
viewHolder.commentBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<PostItem> filterReplyList = new ArrayList<PostItem>();
Intent i = new Intent(ctx, ReplyActivity.class);
i.putExtra("commentID", post.commentID);
// get reply list
for (PostItem reply : replyItemList) {
if (reply.postID.equals(post.commentID)
|| reply.commentID.equals(post.commentID)) {
filterReplyList.add(reply);
}
}
i.putExtra("replyItemList", filterReplyList);
startActivityForResult(i, 0);
}
});
viewHolder.shareBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
String data = "date: " + post.createDate + "\nmsg:" + post.txtMsg;
sendIntent.putExtra(Intent.EXTRA_TEXT, data);
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
});
}
return v;
}
For the task you are trying to do I would strongly recommend you to use Volley library.
Read from here
All you need to do is as below
mRequestQueue = Volley.newRequestQueue(context);
mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache());
mImageView.setImageUrl(BASE_URL + item.image_url, mImageLoader);
Where mImageView is com.android.volley.NetworkImageView instead of a regular ImageView.
Volley takes care of maintaining the cache and the ordering of the images.
if you scroll the listview you will get back recycled convertview, it is not null but it has incorrect imageview. convertView is a view thats created and recycled through scrolling the list. this view makes GC be called less and also save memory for you. it first assigned by your earliest items of list. after you scroll the list, for example item one of list disappears and you see item 15 the convertView of item one is passed again to you. in this time it is not null and it holdes the reference of last imageview, the imageview of item 1.
so this is your problem, you skipped assigning correct imageview to your viewHolder.img.
Ok, what should you do?
the best thing you can do is create in memory cache that holds your downloaded imageview by their URLs as keys of the cache. in getview you check the cache, if it has your URL of current imageview position read from it and set it to viewHolder.img else download the image from internet.
Golden rule is:
ALWAYS OVERWRITE VIEWHOLDER VALUES WITH VALUES OF YOUR ITEM AT INDEX POSITON THAT
GETVIEW PASSES TO YOU
how to create cache? look at Example LRU cache at
http://developer.android.com/training/volley/request.html
and if you want you can also use volley library instead.
if (!post.imageURL.equals("null") && viewHolder.img.getDrawable() == null ) {
new ImageLoader(ctx).execute(viewHolder.img,Constant.comment_imageFolder + post.imageURL);
}
I am guessing that the problem lies here. What happens when you get a recycled view which already has an image from the previous view it was used for? That explains why the image appears in both 1st and 4th position and the change in the display pattern when you scroll.
Get the point? Remove the viewHolder.img.getDrawable() == null and try. See if that helps.