My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
ImageLoading  
Asynchronous Image Loading with AndroidQuery
Updated Jul 13, 2012 by tinyeeliu@gmail.com

Demo

All image loading features and code examples are available with our live demo app on Android Market.

We highly recommended that you try the demo app to get a feel of AQuery's image loading features.

Code

Asynchronous image loading is easy with AQuery.

Simple

//load an image to an ImageView from network, cache image to file and memory

aq.id(R.id.image1).image("http://www.vikispot.com/z/images/vikispot/android-w.png");

Cache Control

//load an image from network, but only cache with file

//this image is huge, avoid memory caching
boolean memCache = false;
boolean fileCache = true;

aq.id(R.id.image1).image("http://www.vikispot.com/z/images/vikispot/android-w.png", memCache, fileCache);

Down Sampling (handling huge images)

//we are loading a huge image from the network, but we only need the image to be bigger than 200 pixels wide
//passing in the target width of 200 will down sample the image to conserve memory
//aquery will only down sample with power of 2 (2,4,8...) for good image quality and efficiency
//the resulting image width will be between 200 and 399 pixels

String imageUrl = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_b.jpg";		
aq.id(R.id.image1).image(imageUrl, true, true, 200, 0);

Related Blog: Downsampling

Fallback Image

//if we are not able to load the image, use a default image (R.drawable.default_image)

String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.id(R.id.image1).image(imageUrl, true, true, 0, R.drawable.default_image);

//make image view "invisible" if image failed to load
imageUrl = "http://a.b.com/invalid.jpg";		
aq.id(R.id.image1).image(imageUrl, true, true, 0, AQuery.INVISIBLE);


//make image view "gone" if image failed to load
aq.id(R.id.image1).image(imageUrl, true, true, 0, AQuery.GONE);

Preloading

//get the bitmap for a previously fetched thumbnail
String thumbnail = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_s.jpg";	
Bitmap preset = aq.getCachedImage(thumbnail);

//set the image view with a thumbnail, and fetch the high resolution image asynchronously
String imageUrl = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_b.jpg";		
aq.id(R.id.image).image(imageUrl, false, false, 0, 0, preset, AQuery.FADE_IN);

Progress

We can show the image loading progress by using the progress() method. Pass in the progress bar id, or any other view id to the progress method, and the view will be shown or hide to display loading progress.

String imageUrl = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_b.jpg";		
aq.id(R.id.image).progress(R.id.progress).image(imageUrl, false, false);

Sample grid item layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="100dip" 
    >
    
    <ProgressBar 		
	android:layout_width="15dip"       
        android:layout_height="15dip"
	android:id="@+id/progress" 
	android:layout_centerInParent="true"
	/>
    
    <ImageView
        android:id="@+id/image"       
        android:layout_width="fill_parent"       
        android:layout_height="75dip"
        />

</RelativeLayout>

Animation

//display the image with a predefined fade in animation
String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";		
aq.id(R.id.image).image(imageUrl, true, true, 0, null, 0, AQuery.FADE_IN);

Rounded Corner

The round option transform the image to a rounded corner image with a specified radius. Note that the value is in pixels (not dip).

Due to performance impact, round corner should not be used for large images.

String url = "http://www.vikispot.com/z/images/vikispot/android-w.png";

ImageOptions options = new ImageOptions();
options.round = 15;

aq.id(R.id.image).image(url, options);

Aspect Ratio

Preserve Image Aspect Ratio
String imageUrl = "http://farm3.static.flickr.com/2199/2218403922_062bc3bcf2.jpg";	
aq.id(R.id.image).image(imageUrl, true, true, 0, 0, null, AQuery.FADE_IN, AQuery.RATIO_PRESERVE);
Fixed Predefined Aspect Ratio
String imageUrl = "http://farm3.static.flickr.com/2199/2218403922_062bc3bcf2.jpg";	

aq.id(R.id.image1).image(imageUrl, true, true, 0, 0, null, 0, AQuery.RATIO_PRESERVE);	

//1:1, a square	
aq.id(R.id.image2).image(imageUrl, true, true, 0, 0, null, 0, 1.0f / 1.0f);		
aq.id(R.id.image3).image(imageUrl, true, true, 0, 0, null, 0, 1.5f / 1.0f);	
	
//16:9, a video thumbnail
aq.id(R.id.image4).image(imageUrl, true, true, 0, 0, null, 0, 9.0f / 16.0f);	
aq.id(R.id.image5).image(imageUrl, true, true, 0, 0, null, 0, 3.0f / 4.0f);

Note

The aspect ratio feature will set the ImageView to use the ScaleType MATRIX and adjust its height to the correct aspect ratio.

Anchor

If the image aspect ratio is taller then the desired aspect ratio, the anchor option can be used to control which vertical portion of the image should be displayed.

Anchor values:

  • 1.0 : Display top of the image
  • 0 : Display the center of the image
  • -1.0 : Display bottom of the image
  • AQuery.ANCHOR_DYNAMIC : Display image with a top bias for photos.

ImageOptions options = new ImageOptions();

options.ratio = 1;
options.anchor = 1.0;
aq.id(R.id.image1).image(imageUrl, options);

Custom Callback

String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";

final int tint = 0x77AA0000;

aq.id(R.id.image1).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback(){

	@Override
	public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){
				
		iv.setImageBitmap(bm);
		
		//do something to the bitmap
		iv.setColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
		
	}
	
});

File (Async)

Load image from a file asynchronously. Down sampling is recommended when loading huge images from camera or gallery to avoid out of memory errors.

Simple
File file = new File(path);        

//load image from file, down sample to target width of 300 pixels  
aq.id(R.id.avatar).image(file, 300);
Callback
File file = new File(path);

//load image from file with callback
aq.id(R.id.avatar).image(file, false, 300, new BitmapAjaxCallback(){

    @Override
    public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){
    	
    	iv.setImageBitmap(bm);
        
    	//do something with the bm
        
    }
    
});

Duplicated URL

//AQuery detects duplicated image urls request and only fetches 1 image and apply them to all associated image views

String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.id(R.id.image1).image(imageUrl);

//no network fetch for 2nd request, image will be shown when first request is completed
aq.id(R.id.image2).image(imageUrl);

BitmapAjaxCallback

All the AQuery image methods uses the BitmapAjaxCallback internally. You can configure and use the callback directly if you prefer.

String imageUrl = "http://farm3.static.flickr.com/2199/2218403922_062bc3bcf2.jpg";	

//create a bitmap ajax callback object
BitmapAjaxCallback cb = new BitmapAjaxCallback();

//configure the callback
cb.url(imageUrl).animation(AQuery.FADE_IN).ratio(1.0f);

//invoke it with an image view
aq.id(R.id.image).image(cb);

Access Cached Images

//returns the cached file by url, returns null if url is not cached
File file = aq.getCachedFile(url);

Zoomable Web Image

In addition to ImageView, a WebView can be used to display an image along with Android build in zoom support for WebView. Image will be centered and fill the width or height of the webview depending on it's orientation.

private void image_zoom(){

	String url = "http://farm4.static.flickr.com/3531/3769416703_b76406f9de.jpg";   	
	aq.id(R.id.web).progress(R.id.progress).webImage(url);
	
}

List View Example

When working with AQuery, make sure the views you want to operate can be "findBy" the view or activity you created with the AQuery object. In the case for rendering list items, create an AQuery object with the item container view.

Example

ArrayAdapter<JSONObject> aa = new ArrayAdapter<JSONObject>(this, R.layout.content_item_s, items){
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
		if(convertView == null){
			convertView = getLayoutInflater().inflate(R.layout.content_item_s, null);
		}
		
		JSONObject jo = getItem(position);
		
		AQuery aq = new AQuery(convertView);
		aq.id(R.id.name).text(jo.optString("titleNoFormatting", "No Title"));
		aq.id(R.id.meta).text(jo.optString("publisher", ""));
		
		String tb = jo.optJSONObject("image").optString("tbUrl");
		aq.id(R.id.tb).progress(R.id.progress).image(tb, true, true, 0, 0, null, AQuery.FADE_IN_NETWORK, 1.0f);
		
		
		return convertView;
		
	}
};

Delay Image Loading

AQuery provide a shouldDelay() method to help you decide whether to load expensive resources when the list is scrolling (flinging) really fast. It's recommended to delay load large images and other resources over the internet.

Please see javadoc for more detail.

ArrayAdapter<Photo> aa = new ArrayAdapter<Photo>(this, R.layout.photo_item, entries){
	
	public View getView(int position, View convertView, ViewGroup parent) {
		
		if(convertView == null){
			convertView = getLayoutInflater().inflate(R.layout.photo_item, parent, false);
		}
		
		Photo photo = getItem(position);
		
		AQuery aq = new AQuery(convertView);
		
		aq.id(R.id.name).text(photo.title);
		aq.id(R.id.meta).text(photo.author);
		
		String tbUrl = photo.tb;
		
		Bitmap placeholder = aq.getCachedImage(R.drawable.image_ph);
		
		if(aq.shouldDelay(position, convertView, parent, tbUrl)){
			aq.id(R.id.tb).image(placeholder, 0.75f);
		}else{
			aq.id(R.id.tb).image(tbUrl, true, true, 0, 0, placeholder, 0, 0.75f);
		}
		
		return convertView;
		
	}
	
};

//apply any custom onScrollListener
aq.id(R.id.list).scrolled(new OnScrollListener(){...});

//apply the adapter
aq.id(R.id.list).adapter(aa);

NOTE

The shouldDelay() method uses the setOnScrollListener() method and will override any previously non-aquery assigned scroll listener. If a scrolled listener is required, use the aquery method scrolled(OnScrollListener listener) to register your listener instead.

ListView, GridView, Gallery, and ExpandableListView are supported. For ExpandableListView, use the variation method:

shouldDelay(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent, java.lang.String url) 

ViewHolder Pattern

ViewHolder pattern optimize performance by caching the views returned by findViewById().

ArrayAdapter<JSONObject> aa = new ArrayAdapter<JSONObject>(this, R.layout.content_item_s, items){
	
	public View getView(int position, View convertView, ViewGroup parent) {
		
		ViewHolder holder;
		
		if(convertView == null){					
			convertView = getLayoutInflater().inflate(R.layout.content_item_s, null);
			holder = new ViewHolder();
			holder.imageview = (ImageView) convertView.findViewById(R.id.tb);
			holder.progress = (ProgressBar) convertView.findViewById(R.id.progress);
			convertView.setTag(holder);
		}else{
			holder = (ViewHolder) convertView.getTag();
		}
		
		JSONObject jo = getItem(position);
		String tb = jo.optJSONObject("image").optString("tbUrl");
		
		AQuery aq = new AQuery(convertView);
		aq.id(holder.imageview).progress(holder.progress).image(tb, true, true, 0, 0, null, 0, 1.0f);
		
		return convertView;
	}
};

Cache Busting

Images on the web usually doesn't change. If your image changes with identical url and would like to refresh the image, simply set file and mem cache to false and it will force the image to be refetched.

String url = "http://www.vikispot.com/z/images/vikispot/android-w.png";

//force a network refetch without any caching
aq.id(R.id.image).image(url, false, false);

//force no proxy cache by appending a random number to url 
String url2 = url + "?t=" + System.currentTimeMillis();
aq.id(R.id.image2).image(url2, false, false);

Network Failure Recovery

If network is disconnected and causing images to failed to load and use fallback images instead, the fallback images will be cached and continue to be served until the network connection is recovered.

When a next subsequent successful connection is established, the fallback image cache will be flushed and allow failed images to be reloaded.

Cache Configuration

By default, AQuery uses the internal file system to cache files, which is only accessible to your app. If you want to use the external SDCard for storing your cached files, use the setCacheDir() function.

	
File ext = Environment.getExternalStorageDirectory();
File cacheDir = new File(ext, "myapp");	
AQUtility.setCacheDir(cacheDir);
	

Sharing Image

In order to share resources to other apps, the file must be on the external storage (SDCard). The makeSharedFile() method create a copy of a cached url to a temporary folder in SDCard. You can then pass the file as an URI and share it with other apps, like Gmail or Facebook.

public void image_send(){
	
	String url = "http://www.vikispot.com/z/images/vikispot/android-w.png";		
	File file = aq.makeSharedFile(url, "android.png");
	
	if(file != null){		
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("image/jpeg");
		intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
		startActivityForResult(Intent.createChooser(intent, "Share via:"), SEND_REQUEST);
	}
}

Configuration

More fine tuning can be done when an application starts. A good place to set the configuration is in the onCreate() method of the application.

public class MainApplication extends Application{

	
	@Override
    public void onCreate() {     
          
        //set the max number of concurrent network connections, default is 4
	AjaxCallback.setNetworkLimit(8);

	//set the max number of icons (image width <= 50) to be cached in memory, default is 20
	BitmapAjaxCallback.setIconCacheLimit(20);

	//set the max number of images (image width > 50) to be cached in memory, default is 20
	BitmapAjaxCallback.setCacheLimit(40);

	//set the max size of an image to be cached in memory, default is 1600 pixels (ie. 400x400)
	BitmapAjaxCallback.setPixelLimit(400 * 400);
        
	//set the max size of the memory cache, default is 1M pixels (4MB)
	BitmapAjaxCallback.setMaxPixelLimit(2000000);		        
        
        super.onCreate();
    }
	
	
}

Maintenance

AQuery provides few utility functions to help you control ajax and caching behavior.

Clean Up

If you use file cache for images, regularly clean the cache dir when the application exits.

Simple

protected void onDestroy(){
	
	super.onDestroy();
	
	//clean the file cache when root activity exit
	//the resulting total cache size will be less than 3M	
	if(isTaskRoot()){
    		AQUtility.cleanCacheAsync(this);
    	}
}

Advance

protected void onDestroy(){
	
	super.onDestroy();
	
	if(isTaskRoot()){

    		//clean the file cache with advance option
    		long triggerSize = 3000000; //starts cleaning when cache size is larger than 3M
    		long targetSize = 2000000;	//remove the least recently used files until cache size is less than 2M
    		AQUtility.cleanCacheAsync(this, triggerSize, targetSize);
	}
	
}

Low Memory

Low memory happens when the device is overloaded with apps. When this happens, we want to remove all images from memory cache.

public class MainApplication extends Application{

    @Override
    public void onLowMemory(){	

	//clear all memory cached images when system is in low memory
	//note that you can configure the max image cache count, see CONFIGURATION
    	BitmapAjaxCallback.clearCache();
    }
	
}
Comment by christop...@inbox.com, Jan 21, 2013

Firstly, I would like to say! wow you guys have done an awesome job with this!

I am trying to implement the first ListView? example, I am stuck... On this line: ArrayAdapter?<JSONObject> aa = new ArrayAdapter?<JSONObject>(this, R.layout.list_item, items){

Where do I get the "items"? it keeps giving me an error when building an items array, I'm not sure what to do here.

Thanks.

Comment by gajendra...@gmail.com, Apr 10, 2013

Can we override AQuery methods in android. Please provide me an example. Thanks in Advance....! Like

aq.id(R.id.name).text(jo.optString("titleNoFormatting", "No Title"));
is it possible to override text method here..

Comment by bilalsam...@gmail.com, Jun 11, 2013

Is there any sample code that uploads image to server using the most great library AQuery?

Comment by azhar19...@gmail.com, Jun 25, 2013

The code was wrong, I can do this!! . <a href="http://www.appsta.com/android-phone">click here</a>

Comment by anhminh....@gmail.com, Jul 23, 2013

Hi,

When using setListAdapter(aa); I can get the onListItemClick called

while aq.id(R.id.list).adapter(aa); don't. Please help, the setListAdaper is too slow in compare to aq.id...

Thanks

MinhDA

Comment by erkushwa...@gmail.com, Oct 29, 2013

Hi,I like your project

Comment by pratik13...@gmail.com, Dec 9, 2013
if(aq.shouldDelay(position, convertView, parent, holder.prodImagePath)){

aq.id(holder.prodImage).image(R.drawable.no_image);
} else {
aq.id(holder.prodImage).progress(view.findViewById(R.id.progressBar1)).image(holder.prodImagePath, false, true, 0, 0, null, AQuery.FADE_IN);
}

Throwing NPE... Please give me Solution.

Comment by okmu...@gmail.com, Jan 24, 2014

android-query-full.0.26.7.jar를 사용하여 이미지를 보여주는데 버그를 발견했습니다. 이미지를 round처리하기 위해 ImageOptions?를 이용했고 이미지가 존재하지 않을때를 처리하기 위해 fallback을 사용했습니다. 버그는 이미지가 유효하지 않을때 bitmap이 생성되지 않았는데 round처리 하는 과정에서 NullPointException?이 발생합니다. 위치는 BitmapAjaxCallback?.java의415라인 입니다.

이 부분이구요.. if(round > 0){

bm = getRoundedCornerBitmap(bm, round);
}

아래와 같이 null처리가 추가되어야 합니다. if(round > 0){

if(bm != null){
bm = getRoundedCornerBitmap(bm, round);
}
}

Thanks you!!

Comment by upupup6...@gmail.com, Apr 6, 2014

Thanks for the Library. Really helpful

Comment by lefebvre...@gmail.com, Apr 24, 2014

Hello here I am newbie in developing my idea of a developer who seeks apli eberger an image on a local server view it in full screen every 5 seconds recommancer Image not available it not existing recommancer all 5s are pouriez you help me?

Comment by ahsan...@gmail.com, Jul 15, 2014

By using Aquery sometime duplicate image in listview row if the row doesn't contain any image...


Sign in to add a comment
Powered by Google Project Hosting