I've been visiting Stack Overflow for many years and it is the first time that I can't find any post that can solve my problem (at least I didn't see any).
I have a GridView
with a custom adapter, which I have overridden to return a custom view made by an ImageView
and a TextView
.
I load the images after JSON parsing them from URLs with an AsyncTask
, storing all the info into an ArrayList
in the doInBackground()
method and calling notifyDataSetChanged()
in the onPostExecute()
method. Everything's fine.
Now my problem is that when I launch the activity it takes a time of 5-10 seconds before the grid view will create and present itself to the user in entity. I'm wondering if there is a way to show the grid view with the text info first and then each image will load. Is this possible or not because they are both created in the same method?
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
View v = null;
if (arg1 == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.custom_product_view, null);
} else {
v = arg1;
}
iv = (ImageView) v.findViewById(R.id.product_image);
imageLoader.DisplayImage(products.get(arg0).getImage(), iv);
TextView tv = (TextView) v.findViewById(R.id.product_price);
tv.setText(products.get(arg0).getPrice());
return v;
}
I also must inform you as you can see from the DisplayImage()
method that I have implemented this lazy loading: Lazy load of images in ListView. It works fine but the thing is that it loads the whole view again. What I want to do is launch the activity, load caption first and then the image will load when it finishes downloading. With this code here, it just lazy loads the whole View that every cell of the grid view contains. I earned some seconds because I don't download all the images at once like before but still it's not what I'm searching for.
Thanks a lot.
Follow this approach.
First, create a custom WebImageView class as follows.
public class WebImageView extends ImageView {
private Drawable placeholder, image;
public WebImageView(Context context) {
super(context);
}
public WebImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WebImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setPlaceholderImage(Drawable drawable) {
placeholder = drawable;
if (image == null) {
setImageDrawable(placeholder);
}
}
public void setPlaceholderImage(int resid) {
placeholder = getResources().getDrawable(resid);
if (image == null) {
setImageDrawable(placeholder);
}
}
public void setImageUrl(String url) {
DownloadTask task = new DownloadTask();
task.execute(url);
}
private class DownloadTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
try {
URLConnection conn = (new URL(url)).openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current=bis.read()) != -1) {
baf.append((byte)current);
}
byte[] imageData = baf.toByteArray();
return BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap result) {
image = new BitmapDrawable(result);
if (image != null) {
setImageDrawable(image);
}
}
}
}
Next, in Activity use the above custom ImageView as follows:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebImageView imageView = (WebImageView) findViewById(R.id.webimage);
imageView.setPlaceholderImage(R.drawable.ic_launcher);
imageView.setImageUrl("http://www.google.co.in/images/srpr/logo3w.png");
}
In brief, you are setting a placeholder image for the ImageView which gets replaced by the actual image when download completes. So the GridView will render immediately without delay.
Implementation Details: So in your custom view (with an image + text) instead of using a simple ImageView, use WebImageView as shown above. When you get the JSON response set the TextView with the caption and the WebImageView with the image url. So the caption will display immediately and the Image will load lazily.