/** == XML Layout ==
*
* <?xml version="1.0" encoding="utf-8"?>
* <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:orientation="vertical"
* android:layout_width="fill_parent"
* android:layout_height="fill_parent"
* >
* <Gallery id="@+id/gallery"
* android:layout_width="fill_parent"
* android:layout_height="wrap_content"
* android:gravity="bottom"
* />
* </LinearLayout>
*
*/
package org.anddev.android.galleryexample;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
public class GalleryExample extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
/* Find the gallery defined in the main.xml
* Apply a new (custom) ImageAdapter to it. */
((Gallery) findViewById(R.id.gallery))
.setAdapter(new ImageAdapter(this));
}
public class ImageAdapter extends BaseAdapter {
/** The parent context */
private Context myContext;
/** URL-Strings to some remote images. */
private String[] myRemoteImages = {
"http://www.anddev.org/images/tiny_tutheaders/weather_forecast.png",
"http://www.anddev.org/images/tiny_tutheaders/cellidtogeo.png",
"http://www.anddev.org/images/tiny_tutheaders/droiddraw.png"
};
/** Simple Constructor saving the 'parent' context. */
public ImageAdapter(Context c) { this.myContext = c; }
/** Returns the amount of images we have defined. */
public int getCount() { return this.myRemoteImages.length; }
/* Use the array-Positions as unique IDs */
public Object getItem(int position) { return position; }
public long getItemId(int position) { return position; }
/** Returns a new ImageView to
* be displayed, depending on
* the position passed. */
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(this.myContext);
try {
/* Open a new URL and get the InputStream to load data from it. */
URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
/* Apply the Bitmap to the ImageView that will be returned. */
i.setImageBitmap(bm);
} catch (IOException e) {
i.setImageResource(R.drawable.error);
Log.e("DEBUGTAG", "Remtoe Image Exception", e);
}
/* Image should be scaled as width/height are set. */
i.setScaleType(ImageView.ScaleType.FIT_CENTER);
/* Set the Width/Height of the ImageView. */
i.setLayoutParams(new Gallery.LayoutParams(150, 150));
return i;
}
/** Returns the size (0.0f to 1.0f) of the views
* depending on the 'offset' to the center. */
public float getScale(boolean focused, int offset) {
/* Formula: 1 / (2 ^ offset) */
return Math.max(0, 1.0f / (float)Math.pow(2, Math.abs(offset)));
}
}
}
3 Comments
Won't the getView(...) method in this snippet makes a network call on the main application thread? If that is the case, this will lock up the GUI and, if the network is slow, will cause the Application Not Responsive error dialog.
Not only that - convertView is also not used. And looks like we'll make those network requests over and over again.
In getView(). both InputStream objects (is and bis) should be closed in a finally block so that the resources will be cleaned up even when an exception occurs.