I am working on an application in which I have a listview, which is getting populated through an ArrayAdapter. All the things are working fine except an issue which has now become quite irritating.
My list view has a custom layout infalted that contains image and then text. The problem is with image part. When I tap on the list after it is populated the images in the list swap there position. Say, for example image associated to 1st cell goes to 3rd and vice versa and so on. It happens only with Images. Text remains at its position. I don't know what the issue is. Please help me out of this severe problem.
Following is my Adapter code:
public class PListAdapter extends ArrayAdapter<Product> {
Context context;
ArrayList<Product> products;
LayoutInflater vi;
ProgressBar mSpinner;
private ImageView imageView;
public void setItems(ArrayList<Product> items) {
this.products = items;
}
public ProductListAdapter(Context context, ArrayList<Product> productList) {
super(context, 0, productList);
// TODO Auto-generated constructor stub
this.context = context;
this.products = productList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
final Product p = products.get(position);
if (p != null) {
if (v == null) {
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.sample_singlerow, null);
}
imageView = (ImageView) v.findViewById(R.id.product_image);
TextView title = (TextView) v.findViewById(R.id.product_title);
TextView summary = (TextView) v.findViewById(R.id.product_summary);
TextView price = (TextView) v.findViewById(R.id.product_price);
TextView type = (TextView) v.findViewById(R.id.product_type);
ImageView pImage = (ImageView) v.findViewById(R.id.persons);
if (imageView != null) {
if (p.getImage() == null) {
if (p.getImageURL() != null) {
new AsyncImageLoader(imageView, p.getImageURL());
}
}
}
if (title != null) {
Log.i("Title: ", p.getName());
title.setText(p.getName());
}
if (summary != null) {
Log.i("Summary: ", p.getDescription());
summary.setText(p.getDescription().substring(0, 110) + "...");
}
if (price != null) {
Log.i("Price: ", p.getPrice());
price.setText(p.getPrice());
}
if (type != null) {
Log.i("Type: ", p.getType());
type.setText(p.getType() + " Person");
}
if (pImage != null) {
try {
if (p.getType().equals("1")) {
pImage.setImageResource(R.drawable.one_person);
} else if (p.getType().equals("2")) {
pImage.setImageResource(R.drawable.two_person);
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
pImage.setImageDrawable(null);
e.printStackTrace();
}
}
}
return v;
}
Edit:
public class AsyncImageLoader {
private final WeakReference imageViewReference;
public AsyncImageLoader(ImageView imageView,String imageUrl) {
imageViewReference = new WeakReference<ImageView>(imageView);
String[] url={imageUrl};
new BitmapDownloaderTask().execute(url);
}
// static int counter = 0;
// int imageNum = 0;
/**
* This Interface in used by {#link AsyncImageLoader} to return a response
* by after loading image
*/
public interface ImageCallback {
public Drawable temp = null;
/**
* Load the Image in imageDrable, Image is loaded form imageUrl
*
* #param imageDrawable
* Image in drawable format
* #param imageUrl
* URL of image to be load
*/
public void imageLoaded(Drawable imageDrawable, String imageUrl);
}
private String LOG_TAG;
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
#Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
// params comes from the execute() call: params[0] is the url.
return downloadBitmap(params[0]);
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null && !(bitmap==null)) {
imageView.setImageBitmap(bitmap);
}
}
}
}
Bitmap downloadBitmap(String url) {
final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
getRequest.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
getRequest.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
} finally {
if ((client instanceof AndroidHttpClient)) {
((AndroidHttpClient) client).close();
}
}
return null;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
#Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
}
Please let me know what is the issue. Anxiously waiting for your response.
As I can see, you have some troubles with Views reusage in Adapter and asynchronous loading.
To optimize performance and memory, instead of inflating views repeatedly, Android tries to "cache" list items in ListView's recycler - that means that the same View (list item) will be used several times, each time for different data item.
If so - let's check what will happen if you'll scroll the existing list: some view will be infated, filled with data and will start to download image for ImageView. In separate thread.
And now what if this View will be reused for another data item, before previous Image was successfully loaded? Currently, a new AsyncTask will be started for this image. And here comes a racing condition, noone knows in which order the result will be returned from the AsyncTask.
So I would recommend you either to store AsyncTask with a View (in Tag, for example), or to make some hashmap.
The main purpose - to determine when bitmap loading is complete - was this image used for another bitmap request or not, if it was - skip image setting, as it's outdated.
This approach will prevent imageViews from displaying wrong image for another item.
Hope it helps, good luck
you need to add bydefault image if the image url is null, Just add else check and add any place holder
Related
I am tying to lazy load images into my ListView, the images are loading fine, but I've a problem. While loading the images get interchanged.
Let's say that the ListView has 10 rows. It loads the images for 1st row, it displays it in the 1st row, then it loads the image for the 2nd row. It displays in the 2nd row for a moment and then it displays the image for the 2nd row in the 1st row. Then the ImageView in row1 switches between images of 1st row and 2nd. Similarly while loading images of next rows. the previous row's images get switched between. And then after loading all the images, everything gets displayed correctly.
Here's my code
Adapater class:
public class FamilyMemberListAdapter extends ArrayAdapter<Map<String, String>> {
List<Map<String, String>> familyMemberList = new ArrayList<Map<String, String>>();
private Activity activity;
public FamilyMemberListAdapter(Activity activity,
List<Map<String, String>> familyMemberList) {
super(activity, R.layout.activity_gch_family_members, familyMemberList);
this.activity = activity;
this.familyMemberList = familyMemberList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(this.getContext()).inflate(
R.layout.activity_gch_family_member_item, parent, false);
holder = new ViewHolder();
holder.lblFamilyMemberName = (TextView) convertView
.findViewById(R.id.lblFamilyMemberItem);
holder.lblFamilyMemberRelation = (TextView) convertView
.findViewById(R.id.lblFamilyMemberRelationItem);
holder.imgProfilePic = (ImageView) convertView
.findViewById(R.id.imgvProfilePic);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
int accountId = Integer.valueOf(familyMemberList.get(position).get(
"accountId"));
holder.lblFamilyMemberName.setText("Name: "
+ familyMemberList.get(position).get("name"));
holder.lblFamilyMemberRelation.setText("Relation: "
+ familyMemberList.get(position).get("relation"));
if (holder.imgProfilePic != null) {
new ImageDownloaderTask(holder.imgProfilePic).execute(String
.valueOf(accountId));
}
return convertView;
}
#Override
public int getCount() {
return familyMemberList.size();
}
static class ViewHolder {
TextView lblFamilyMemberName;
TextView lblFamilyMemberRelation;
ImageView imgProfilePic;
}
}
Imageloader AsyncTask:
public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
public ImageDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Bitmap doInBackground(String... params) {
String responseText = null;
HttpClient httpClient = ServiceHelper.getHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(RestApiPaths.GET_PROFILE_PIC + accountId);
try {
HttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap that android understands
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
Log.d(TAG, responseText);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#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 {
Drawable placeholder = imageView.getContext().getResources().getDrawable(R.drawable.holder_pic_side);
imageView.setImageDrawable(placeholder);
}
}
}
}
}
I've created a Static class for the ListView items. Still Why is the images go on interchanging while loading. Please tell me what I'm doing wrong here.
Add holder.imgProfilePic.setTag(accountId); before you call the AsyncTask. Add an extra parameter accountId to your task. Then in onPostExecute check if it is the same accountId as in the image view
Maybe try to use libraries like picasso or universal image loader or something.
They have solved most of problems with image loading
I am filling a GridView with my facebook friends' photo.
When I use my account of tester with few friends my application works good. But when I use my main account and I scroll quickly my application I get This error:
AndroidRuntime(6131): java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3#42230f20 rejected from java.util.concurrent.ThreadPoolExecutor#4206af70[Running, pool size = 128, active threads = 128, queued tasks = 10, completed tasks = 61]
otherwise
If i scroll a lot i get this error:
java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:299)
Caused by: java.lang.NullPointerException at it.alfonso.utils.GetImageFromUrlAsyncTask.downloadImage(GetImageFromUrlAsyncTask.java:62)
if (facebookAdapter == null) {
facebookAdapter = new ImageAdapterFacebook(this, facebookResponses);
gridview.setAdapter(facebookAdapter);
}
else {
gridview.setAdapter(facebookAdapter);
}
My adapeter for my GridView
public class ImageAdapterFacebook extends BaseAdapter {
private Context mContext;
private FacebookResponses facebookFrinds;
public ImageAdapterFacebook(Context c, FacebookResponses facebookFrinds) {
mContext = c;
this.facebookFrinds = facebookFrinds;
}
public int getCount() {
return facebookFrinds == null ? 0 : facebookFrinds.getData().length;
}
public Object getItem(int position) {
return facebookFrinds == null ? null
: facebookFrinds.getData()[position];
}
public long getItemId(int position) {
return position;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View amico, ViewGroup parent) {
final ImmageViewHolder viewHolder;
if (amico == null) { // if it's not recycled, initialize some attributes
LayoutInflater li = (LayoutInflater) parent.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
amico = li.inflate(R.layout.details_img_facebook_user, parent,
false);
viewHolder = new ImmageViewHolder();
viewHolder.userImage = (ImageView) amico
.findViewById(R.id.userLikesimg);
amico.setTag(viewHolder);
} else {
viewHolder = (ImmageViewHolder) amico.getTag();
}
if (facebookFrinds != null) {
viewHolder.userImage.setImageResource(R.drawable.image_loader);
String imgUserurl = facebookFrinds.getData()[position]
.getPic_square();
// Create an object for subclass of AsyncTask
GetImageFromUrlAsyncTask task = new GetImageFromUrlAsyncTask(
mContext, new DownloadImageLister() {
#Override
public void onDownloadImageSucces(Bitmap immagine) {
viewHolder.userImage.setImageBitmap(immagine);
}
#Override
public void onDownloadImageFail() {
System.out.print("errore");
}
});
task.execute(imgUserurl);
}
return amico;
}
public class ImmageViewHolder {
ImageView userImage;
}
}
My AsyncTask
public class GetImageFromUrlAsyncTask extends AsyncTask<String, Void, Bitmap> {
private Context contesto;
private DownloadImageLister listenerImage;
public GetImageFromUrlAsyncTask(Context context,
DownloadImageLister listener) {
contesto = context;
listenerImage = listener;
}
#Override
protected Bitmap doInBackground(String... urls) {
Bitmap map = null;
for (String url : urls) {
map = downloadImage(url);
}
return map;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null ) {
listenerImage.onDownloadImageSucces(result);
}
if (result == null ) {
listenerImage.onDownloadImageFail();
}
}
// Creates Bitmap from InputStream and returns it
private Bitmap downloadImage(String url) {
Bitmap bitmap = null;
InputStream stream = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
try {
stream = getHttpConnection(url);
bitmap = BitmapFactory.decodeStream(stream, null, bmOptions);
stream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return bitmap;
}
// Makes HttpURLConnection and returns InputStream
private InputStream getHttpConnection(String urlString) throws IOException {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
try {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return stream;
}
}
Since you are performing so many requests for each image load your app is crashing. You could use the Volley Android library and its NetworkImageView. This is what several Google apps are using for async image loading and http requests. There is a good tutorial explaining how to use it here: http://www.captechconsulting.com/blog/clinton-teegarden/android-volley-library-tutorial.
Hope that helps!
I have been reading through a lot of answers of questions that are similar to mine, but still having problem fixing my issue. I have a project that is an RSS Reader that loads in images in the background with an AsyncTask class. The program works, except if the user scrolls quickly then the images sometimes do not load in my rows. They never load in the incorrect spot, it just seems like they are skipped if the user scrolls quickly. Also, on start-up, only 2 or 1 of the images in my listview load out of the 4 rows that the user can see.
I know the problem has something to do with the WeakReference object that I use, but I am not sure how to implement it in a better way...
This is my RssListAdapter, which contains my Async class as well.
public class RssListAdapter extends ArrayAdapter<JSONObject>
{
TextView textView;
ImageView imageView;
JSONObject jsonImageText;
ProgressDialog progressDialog;
Activity activity2;
View rowView;
public RssListAdapter(Activity activity, List<JSONObject> imageAndTexts)
{
super(activity, 0, imageAndTexts);
activity2 = activity;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
Activity activity = (Activity) getContext();
LayoutInflater inflater = activity.getLayoutInflater();
// Inflate the views from XML
View rowView = (View) inflater
.inflate(R.layout.image_text_layout, null);
jsonImageText = getItem(position);
// ////////////////////////////////////////////////////////////////////////////////////////////////////
// The next section we update at runtime the text - as provided by the
// JSON from our REST call
// //////////////////////////////////////////////////////////////////////////////////////////////////
textView = (TextView) rowView.findViewById(R.id.job_text);
imageView = (ImageView) rowView.findViewById(R.id.feed_image);
BitmapDownloaderTask task = new BitmapDownloaderTask();
Spanned text;
try
{
text = (Spanned) jsonImageText.get("text");
textView.setText(text);
}
catch (JSONException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
task.execute();
return rowView;
}
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap>
{
private String url;
private RssListAdapter adapter;
private WeakReference<ImageView> imageViewReference = null;
#Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params)
{
imageViewReference = new WeakReference<ImageView>(imageView);
Bitmap img = null;
try
{
if (jsonImageText.get("imageLink") != null)
{
System.out.println("XXXX Link found!");
String url = (String) jsonImageText.get("imageLink");
URL feedImage = new URL(url);
HttpURLConnection conn = (HttpURLConnection) feedImage
.openConnection();
InputStream is = conn.getInputStream();
img = BitmapFactory.decodeStream(is);
}
}
catch (MalformedURLException e)
{
// handle exception here - in case of invalid URL being parsed
// from the RSS feed item
}
catch (IOException e)
{
// handle exception here - maybe no access to web
}
catch (JSONException e)
{
// textView.setText("JSON Exception");
}
return img;
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap)
{
if (isCancelled())
{
bitmap = null;
}
if (imageViewReference != null)
{
ImageView imageView = imageViewReference.get();
if (imageView != null)
{
imageView.setImageBitmap(bitmap);
}
}
}
#Override
// Before images are loaded
protected void onPreExecute()
{
if (imageViewReference == null)
{
imageView.setImageResource(R.drawable.stub);
}
}
}
}
You should check the official Android "Displaying Bitmaps Efficiently" tutorial on how to load and display bitmaps efficiently. It comes with a ready to use piece of code.
i want to display images from mysql server(testing in localhost) using imageurl,i have images in a filder on my server,in an android client app as gridview along with text.how do i use imageurl in my code?
mymainmenu.java
public class MainMenu extends Activity {
GridView gridView;
static final String[] MOBILE_OS = new String[] {
"Android", "iOS","Windows", "Blackberry" };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu_list);
gridView = (GridView) findViewById(R.id.gridView1);
gridView.setAdapter(new ImageAdapter(this, MOBILE_OS));
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(
getApplicationContext(),
((TextView) v.findViewById(R.id.grid_item_label))
.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
my imageadapter.java:
public class ImageAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
public ImageAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from list.xml
gridView = inflater.inflate(R.layout.list, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
String mobile = mobileValues[position];
if (mobile.equals("Windows")) {
imageView.setImageResource(R.drawable.imggrid);
} else if (mobile.equals("iOS")) {
imageView.setImageResource(R.drawable.imggrid);
} else if (mobile.equals("Blackberry")) {
imageView.setImageResource(R.drawable.imggrid);
} else {
imageView.setImageResource(R.drawable.imggrid);
}
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return mobileValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
I dnt know how to use the following in my code:
try {
URL url = new URL(imageFileURL);
URLConnection conn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection)conn;
httpConn.setRequestMethod("GET");
httpConn.connect();
if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpConn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
img.setImageBitmap(bitmap);
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Put the image downloading code in a AsyncTask. Here is the explanation.
Execute one instance of asynctask in your getView method, i.e to fetch one image everytime.
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView mImageView;
public void setImageView(ImageView img) {
mImageView = img;
}
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Call task.setImageView(yourImageViewinGrid) before executing your AsyncTask to let it know where to set the image after downloading.
To get the image, you have to do something like :
URL new_url = new URL("your url");
Bitmap image_bitmap = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream()); ImageView image_view = new ImageView(this);
image_view.setImageBitmap(image_bitmap);
Anyway, it's better to download the image as background task. What I actually do is to create a custom view with one private inner class that extend AsyncTask to download the image for you.
I dnt know how to use the following in my code:
that code will download the image for you, you can place in separate thread either AsyncTask or Thread and set the downloaded image in the imageview... simple as that. There are so many example on the web you can google it out
EIDTED
code to download the image
public class AsyncFetchImage extends AsyncTask<String, Void, Bitmap>{
private WeakReference<ImageView> imageReference;
// private WeakReference<Dialog> dialogReferance;
public AsyncFetchImage(ImageView imageview) {
imageReference = new WeakReference<ImageView>(imageview);
// dialogReferance = new WeakReference<Dialog>(dialog);
}
#Override
protected Bitmap doInBackground(String... s) {
return downloadImage(s[0]);
}
private Bitmap downloadImage(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Nixit");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HttpStatus.SC_OK){
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if(entity != null){
InputStream is = null;
try{
is = entity.getContent();
final Bitmap bit = BitmapFactory.decodeStream(is);
return bit;
}finally{
if(is != null)
is.close();
entity.consumeContent();
}
}
} catch (IOException e) {
e.printStackTrace();
return null;
} finally{
if(client != null){
client.close();
}
}
Log.i("Image Fetch","Image Fetch Complete");
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
if(isCancelled()){
result = null;
}
if(imageReference != null){
ImageView imageView = imageReference.get();
// Dialog di = dialogReferance.get();
if (imageView != null) {
imageView.setImageBitmap(result);
// di.show();
}
}
}
}
How to use:-
imageView = (ImageView)dialog.findViewById(R.id.imageView1);
AsyncFetchImage fetchImage = new AsyncFetchImage(imageView);
fetchImage.execute(url);
You can use this in getview method of adapter
Hope that help
I am developing Android apps,
once part of this apps is creating a GridView that contain some image (the image is loaded from URL),
then another activity that show the selected image in full screen will be appeared when one of image in GridView is onClick.
Problem:
When I enter the GridView activity, it takes some second to load all image in gridview normally.
Then I click one of image to enter the full screen activity and click back button to go back to GridView,
but, it takes some second to loading when go back to gridview, just like loading all image again.
I wonder why the gridview activity will loading for a few second when onResume?
For example, in Google Play, the full screen view of sample image in any apps can be back to previous view immediately.
Enclosed code:
GridView:
public class ManagePhoto extends Activity {
ImageAdapter ia;
GridView gridview;
InputStream inputStream;
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
TextView tvRunningMark;
boolean bRunning;
String[] purl;
Bitmap[] bm;
String the_string_response;
TouchImageView touch;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_manage);
//gv is Gobal Value
final Gvalue gv = ((Gvalue) getApplicationContext());
gridview = (GridView) findViewById(R.id.gv_photo);
gridview.setOnItemClickListener(new GridView.OnItemClickListener() {
public void onItemClick(AdapterView adapterView, View view,int position, long id) {
gv.setbm(bm[position]);
Intent myIntent = new Intent(adapterView.getContext(), FullScreenImage.class);
startActivityForResult(myIntent, 0);
}
});
new GridTask().execute();
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return purl.length;
}
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);
imageView.setLayoutParams(new GridView.LayoutParams(200,200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
try {
bm[position] = loadBitmap(purl[position]);
imageView.setImageBitmap(bm[position]);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageView;
}
}
class GridTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPostExecute(Void result) {
gridview.setAdapter(ia);
final LinearLayout llo_probar = (LinearLayout)findViewById(R.id.llo_probar);
llo_probar.setVisibility(LinearLayout.GONE);
gridview.setVisibility(GridView.VISIBLE);
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(String... values) {
}
#Override
protected Void doInBackground(Void... params) {
getphoto();
bm = new Bitmap[purl.length];
ia = new ImageAdapter(ManagePhoto.this);
return null;
}
}
private Bitmap loadBitmap(String url) throws MalformedURLException,IOException {
return BitmapFactory.decodeStream(new FlushedInputStream(
(InputStream) new URL(url).getContent()));
}
class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(final InputStream inputStream) {
super(inputStream);
}
#Override
public long skip(final long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int bytesRead = read();
if (bytesRead < 0) { // we reached EOF
break;
}
bytesSkipped = 1;
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
public void getphoto(){
final Gvalue gv = ((Gvalue) getApplicationContext());
final TextView tv_fn = (TextView) findViewById(R.id.tv_fn);
String result = "";
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("sql",
("select * from personal_photo where member_id = " + gv.getuid())));
InputStream is = null;
// http post
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://" + gv.getserverIP()
+ "/android_getdata.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}
// convert response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}
// parse json data
try {
List url = new ArrayList();
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
url.add(json_data.getString("save_location"));
}
int size = url.size();
purl = new String[size];
for (int j = 0; j < size; j++) {
purl[j] = (String) url.get(j);
}
} catch (JSONException e) {
Log.e("log_tag", "Error parsing data " + e.toString());
}
}
public void toast(String text) {
Toast.makeText(ManagePhoto.this, text, 5).show();
}
}
Full screen:
public class FullScreenImage extends Activity {
TouchImageView touch;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
new ShowPhotoTask().execute();
}
class ShowPhotoTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPostExecute(Void result) {
setContentView(touch);
}
#Override
protected void onPreExecute() {
setContentView(R.layout.full_image);
}
#Override
protected void onProgressUpdate(String... values) {
}
#Override
protected Void doInBackground(Void... params) {
final Gvalue gv = ((Gvalue) getApplicationContext());
touch = new TouchImageView(FullScreenImage.this);
touch.setMaxZoom(4f); // change the max level of zoom, default is 3f
touch.setImageBitmap(gv.getbm());
return null;
}
}
}
From your getView code in your ImageAdapter, everytime you will load the image from the internet again.
You should download the image to local, next time, when your set the image, you try to get it from local firstly.
As well you should put the get bitmap in the thread as you have putting the parse JSON in the thread.
Here is an demo, i think it will help you.
In your gridview onclick you are starting activity with startActivityForResults(intent,0); replace it with startActivity(intent);
also when you are finishing the FullScreenActivity just use finish();
might solve your problem
It's so slow because you don't perform your operations with background threads, caching..
A simple and better solution could be a collection that contains all your bitmaps inserted by AsyncTasks that you'll execute to download the pictures.
There are better solutions but they are more difficult to implement.
For example you can consider the possibility to keep a thread pool that resolves your runnables represented by "download the http://jhon.doe.jpg" and then "show now on the UI thread".
As you have written below function inside the getView() method:
bm[position] = loadBitmap(purl[position]);
I would say you should implement code to load Image Asynchronously. In this logic, image is synced in your memory card once its downloading is done. So next time it will load directly from memory card instead of loading it from web again.
Here is a code example you can give a try: Android - Universal Image Loader