I am relatively new to android development and i am trying to create a custom ListView with an ImageView and TextView. I am converting a URL into a bitmap image and then trying to display the image in an imageView. However I am getting an error and my application crashes immediately. The was able to display a drawable in my imageView and I made some modifications and tried to display a bitmap and then my application crashed. Any help would be greatly appreciated. Here are my 3 classes :
EDIT I used an asynctask to obtain the bitmap image on a separate thread and now my app does not crash anymore. But it does not display the listview when I start the activity. Here is my updated code.
EDIT I changed my code again and I am only passing an imageView in the execute method of my async task. I am now able to see the text in my listview, but I do not see the image. here is my edited code.
EDIT I used the debugger to find out why the bitmap wasn’t getting displayed and i found out that my bitmap variable was null. This was because I had not added internet permissions. After adding the permissions my app started to crash at the given line :
b = BitmapFactory.decodeStream(image_url.openConnection() .getInputStream());
I had gotten a RuntimeException due to an OutofMemory error. I am not sure how to solve this. i would appreciate any help. thanks !
Here is my Loadimage AsyncTask Class:
public class LoadImage extends AsyncTask<String, Integer, Bitmap>{
Context callingContext = null;
Bitmap b = null;
ImageView view;
public LoadImage(ImageView view){
this.view = view;
}
@Override
protected Bitmap doInBackground(String... arg0) {
// TODO Auto-generated method stub
String p_url = "http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png";
Bitmap b = null;
try {
URL image_url = new URL(p_url);
b = BitmapFactory.decodeStream(image_url.openConnection() .getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b;
}
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
view.setImageBitmap(result);
}
}
Your code is crashing because you are loading the image file off the server on the UI thread while in strict mode. This is generally considered bad practice because if the image takes a long time to download, your app will appear to have locked up.
Strict mode is forcing the crash (its throwing an exception). If you disable strict mode, it should let your app work fine. However the problem with doing network I/O on your UI thread remains.
The better long term solution is to use something like an AsyncTask. This will load your image on a different thread, thus keeping your app responsive. The documentation for AsyncTask has a simple example for downloading the image, and this helper page has more information.
For an example, I’d probably change your code to something like this (please note I’m writing this without a test run, so there maybe a few bugs):
I’d change your List entry to be:
And then only pass in the icon URL’s to your list.
Next create an AsyncTask:
And then for your Adapter, instead of setting the image, do:
That should be enough to get you started. Please note that there are a couple of issues with this sample:
not hold onto reference to either Views or Activities (or other such
objects) in an AsyncTask like I did.
the list changes, you might have old thumbnails show up.
view is recycled, an old thumbnail might show up.