Universal-imageloader Source Code Flow Analysis (ii)--Picture loading process _imageloader Source analysis

Source: Internet
Author: User
Objective

In the previous article, the configuration properties of Imageloader were described. Here's a chat about actual loading. Picture configuration

When the configuration is complete, this is how the picture is loaded in the actual code:
Imageloader.displayimage (image. URL, ImageView, imageloaderoption);

Configuration code:

private static Displayimageoptions Optionsdelay = new Displayimageoptions.builder ()
            . showimageonloading ( R.drawable.empty_photo)//resource or drawable
            . Showimageforemptyuri (R.drawable.empty_photo)//resource or Drawable
            . Showimageonfail (R.drawable.empty_photo)//resource or drawable
            . Resetviewbeforeloading (False)  //Default
            . delaybeforeloading. Cacheinmemory (
            True). Cacheondisk (
            true)
            . Imagescaletype (imagescaletype.exactly)//Is compressed
            . Bitmapconfig (Bitmap.Config.RGB_565)//Image pixel
            . Build ();

Displayimageoptions's source code is simpler, here is not detailed. or combined with the implementation of display, look at the specific role of these parameters. DisplayImage

/** * @param uri Image uri (i.e. "Http://site.com/image.png", "file:///mnt/sdcard/image.png") * @param
     Imageaware {@linkplain Imageaware image aware View} * which should display image                          * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions options} for Image * decoding and displaying. If <b>null</b>-Default display image options * {@linkplain Imageloaderconfigura tion.
     Builder#defaultdisplayimageoptions (displayimageoptions) * from configuration} would be used. * @param targetsize {@linkplain imagesize} Image target size. If <b>null</b>-size would depend on the view * @param listener {@linkplain Imageloadinglistener Listener} for image loading process. Listener fires * Events on UI thread if this is called on UI thread.
     * @param progresslistener {@linkplain Imageloadingprogresslistener * Listener} for Imag e Loading progress. Listener fires events on UI thread if it is called on UI thread. Caching on disk should is enabled in * {@linkplain com.nostra13.universalimageloader.core.Dis
     Playimageoptions Options} to make * this listener work. * @throws illegalstateexception If {@link #init (imageloaderconfiguration)} method wasn ' t called before * @throws I Llegalargumentexception if passed <b>imageAware</b> is null/public void DisplayImage (String uri, imag Eaware Imageaware, Displayimageoptions options,imagesize targetsize, Imageloadinglistener Listener,  Imageloadingprogresslistener Progresslistener)
Targetsize

Let's take a look at the targetsize of this parameter.

if (targetsize = = null) {
            targetsize = Imagesizeutils.definetargetsizeforview (Imageaware, Configuration.getmaximagesize ());
        }

The default targersize,targersize is calculated based on the size of the control and the imagesize of the configuration.

Then look at how the Getmaximagesize () is obtained, by default the size of the screen.

ImageSize getmaximagesize () {Displaymetrics displaymetrics = Resources.getdisplaymetrics ();
        int width = Maximagewidthformemorycache;
        if (width <= 0) {width = displaymetrics.widthpixels;
        int height = Maximageheightformemorycache;
        if (height <= 0) {height = displaymetrics.heightpixels;
    Return to New ImageSize (width, height);
         /* * @param maximagewidthformemorycache Maximum image width which'll be used for memory saving during decoding * An image to {@link Android.graphics.Bitmap Bitmap}. <b>default value-device ' s screen width</b> * @param maximageheightformemorycache Maximum image Heig HT which is used for memory saving during decoding * A image to {@link Android.graphics.Bitmap Bitmap}. <b>default value</b>-Device ' s screen height * *

Come back and see Definetargetsizeforview's implementation:

public static ImageSize Definetargetsizeforview (Imageaware imageaware, ImageSize maximagesize) {
        int width = Imageaware.getwidth ();
        if (width <= 0) width = maximagesize.getwidth ();

        int height = imageaware.getheight ();
        if (height <= 0) height = maximagesize.getheight ();

        return new ImageSize (width, height);
    }

So we understand how the targetsize is calculated, and we continue to look down: imageloaderengine

Imageloaderengine (imageloaderconfiguration configuration) {
        this.configuration = configuration;

        Taskexecutor = Configuration.taskexecutor;
        Taskexecutorforcachedimages = configuration.taskexecutorforcachedimages;

        Taskdistributor = Defaultconfigurationfactory.createtaskdistributor ();
    }

This illustrates a very important imageloader global variable engine.
The creation method is the code above.
Taskexecutor,taskexecutorforcachedimages can take a look at a configuration note.

public static Executor Createtaskdistributor () {return
        Executors.newcachedthreadpool createthreadfactory ( Thread.norm_priority, "uil-pool-d-"));
    }

Above is the code created by Taskdistributor, followed by the implementation of the taskdistributor to explain.
Let's go back and watch the Imageloader display process:

String Memorycachekey = Memorycacheutils.generatekey (URI, targetsize);
 Engine.preparedisplaytaskfor (Imageaware, Memorycachekey);

Memorycachekey gets a keyword based on the picture URL and picture size.

Private final Map<integer, string> cachekeysforimageawares = Collections
            . Synchronizedmap (New hashmap< Integer, string> ());
/**
     * Associates <b>memoryCacheKey</b> with <b>imageaware</b>. Then it helps to define image URI was loaded into View at
     * exact moment.
     *
    /void Preparedisplaytaskfor (Imageaware imageaware, String memorycachekey) {
        cachekeysforimageawares.put ( Imageaware.getid (), memorycachekey);
    

Next read: Listener

Listener.onloadingstarted (URI, Imageaware.getwrappedview ());
@param listener {@linkplain Imageloadinglistener listener} for image loading process. Listener fires
* Events on UI thread if it is called on UI thread.
Here's a quick look at the listener created by default.
The public interface Imageloadinglistener can listen for the loaded state.
The default created Simpleimageloadinglistener is an empty listener that can be customized according to the individual.

Next look:
Bitmap bmp = Configuration.memoryCache.get (Memorycachekey); The process of hitting data in MemoryCache

When the data is successfully queried from the MemoryCache, the code is as follows:

if (options.shouldpostprocess ()) {
                Imageloadinginfo imageloadinginfo = new Imageloadinginfo (URI, Imageaware, Targetsize, Memorycachekey,
                        options, Listener, Progresslistener, Engine.getlockforuri (URI));
                Processanddisplayimagetask displaytask = new Processanddisplayimagetask (engine, BMP, Imageloadinginfo,
                        Definehandler (options));
                if (options.issyncloading ()) {
                    displaytask.run ();
                } else {
                    engine.submit (displaytask);
                }}
            Else {
                Options.getdisplayer (). Display (BMP, Imageaware, loadedfrom.memory_cache);
                Listener.onloadingcomplete (URI, Imageaware.getwrappedview (), BMP);
            

PostProcess Description
* Sets Bitmap processor which'll be process bitmaps before the would be they in
* {@lin K Com.nostra13.universalimageloader.core.imageaware.ImageAware image aware view} but
* after they ' ll have been In memory cache.
/
You can join postprocess to do some work before the picture is displayed, either synchronously or asynchronously.
When PostProcess is not set, by default, that is, using Setimagebitmap in Imageaware, setting bitmap finish setting.
Options.getdisplayer (). Display (BMP, Imageaware, Loadedfrom.memory_cache);
Public final class Simplebitmapdisplayer implements Bitmapdisplayer {
@Override
public void display (Bitmap Bitmap, Imageaware imageaware, Loadedfrom loadedfrom) {
Imageaware.setimagebitmap (bitmap);
}
The picture is not in memory process

if (options.shouldshowimageonloading ()) {
                imageaware.setimagedrawable (options.getimageonloading) ( configuration.resources);//Configure load wait graph to display load wait picture.
            Else if (options.isresetviewbeforeloading ()) {
                imageaware.setimagedrawable (null);
            }

            Imageloadinginfo imageloadinginfo = new Imageloadinginfo (URI, Imageaware, Targetsize, Memorycachekey,
                    options, Listener, Progresslistener, Engine.getlockforuri (URI);//Save relevant information to record
            loadanddisplayimagetask displaytask = new Loadanddisplayimagetask (engine, Imageloadinginfo,
                    definehandler (options));
                    Focus on loading the picture task
            if (options.issyncloading ()) {
                displaytask.run ();
            } else {
                engine.submit ( displaytask);
                }

Here we take a look at the specific implementation of Loadanddisplayimagetask this task.

Private Bitmap Tryloadbitmap () throws taskcancelledexception {Bitmap = null; try {File imagefile = Configuration.diskCache.get (URI);//Get Picture from DiskCache (imagefile!= null &A mp;& imagefile.exists () && imagefile.length () > 0) {l.d (Log_load_image_from_disk_cache, ME
                Morycachekey);

                Loadedfrom = Loadedfrom.disc_cache;
                Checktasknotactual ();
                Bitmap = Decodeimage (Scheme.FILE.wrap (Imagefile.getabsolutepath ()));
            Get the bitmap from the ImageFile. } if (bitmap = null | | bitmap.getwidth () <= 0 | | bitmap.getheight () <= 0) {L.D (Log_loa
                D_image_from_network, Memorycachekey);

                Loadedfrom = Loadedfrom.network;
                String imageurifordecoding = URI; if (Options.iscacheondisk () && Trycacheimageondisk ()) {//download pictures from the network to disk.
               The following article introduces the Trycacheimageondisk method     ImageFile = Configuration.diskCache.get (URI);
                    if (imagefile!= null) {imageurifordecoding = Scheme.FILE.wrap (Imagefile.getabsolutepath ());

                }//If iscacheondisk==false, decode directly from URI.
                Checktasknotactual ();

                Bitmap = Decodeimage (imageurifordecoding); if (bitmap = null | | bitmap.getwidth () <= 0 | | bitmap.getheight () <= 0) {firefailevent (Failtyp
                E.decoding_error, NULL);
        The catch (IllegalStateException e) {firefailevent (failtype.network_denied, NULL);
        catch (Taskcancelledexception e) {throw e;
            catch (IOException e) {L.E (e);
        Firefailevent (Failtype.io_error, E);
            catch (OutOfMemoryError e) {L.E (e);
        Firefailevent (Failtype.out_of_memory, E);
     catch (Throwable e) {       L.E (e);
        Firefailevent (Failtype.unknown, E);
    return bitmap; }

The above code requires a separate explanation. Decode Decoder Code

Decodeimage (Scheme.FILE.wrap (Imagefile.getabsolutepath ()));
Decodeimage the file into bitmap

Viewscaletype Viewscaletype = Imageaware.getscaletype ();
        Imagedecodinginfo decodinginfo = new Imagedecodinginfo (Memorycachekey, Imageuri, Uri, Targetsize,
                ViewScaleType, Getdownloader (), options);
        Return Decoder.decode (Decodinginfo);

This part of the code is not explained, this part can refer to the Google official provided by the imagefetcher explanation.

Public Bitmap decode (Imagedecodinginfo decodinginfo) throws IOException {Bitmap decodedbitmap;

        Imagefileinfo Imageinfo;
        InputStream ImageStream = Getimagestream (Decodinginfo);
            if (ImageStream = = null) {L.E (Error_no_image_stream, Decodinginfo.getimagekey ());
        return null;
            try {imageinfo = defineimagesizeandrotation (ImageStream, decodinginfo);
            ImageStream = Resetstream (ImageStream, decodinginfo);
            Options decodingoptions = preparedecodingoptions (imageinfo.imagesize, decodinginfo);
        Decodedbitmap = Bitmapfactory.decodestream (ImageStream, NULL, decodingoptions);
        finally {ioutils.closesilently (imagestream);
        } if (Decodedbitmap = = null) {L.E (Error_cant_decode_image, Decodinginfo.getimagekey ()); else {Decodedbitmap = Considerexactscaleandorientatiton (Decodedbitmap, Decodinginfo, ImageInfo.exif.rotation, ImageInfo.exif.flipHorizontal);
    return decodedbitmap; }
Local cache Network Load picture function Trycacheimageondisk
/** @return <b>true</b>-If image was downloaded successfully;
        <b>false</b>-otherwise * private Boolean trycacheimageondisk () throws Taskcancelledexception {

        L.D (Log_cache_image_on_disk, Memorycachekey);
        Boolean loaded;
            try {loaded = Downloadimage ();
                if (loaded) {int width = Configuration.maximagewidthfordiskcache;
                int height = Configuration.maximageheightfordiskcache;
                    if (Width > 0 | | height > 0) {l.d (log_resize_cached_image_file, Memorycachekey); Resizeandsaveimage (width, height);
            Todo:process boolean Result}} catch (IOException e) {L.E (e);
        loaded = false;
    return loaded; Private Boolean Downloadimage () throws IOException {InputStream is = Getdownloader (). GetStream (URI, option
S.getextrafordownloader ());        if (is = = null) {L.E (Error_no_image_stream, Memorycachekey);
        return false;
            else {try {return Configuration.diskCache.save (URI, was, this);
            Finally {ioutils.closesilently (IS); }
        }
    }

The locally saved picture is cropped by default by the screen resolution file size.

As shown above is the whole process of picture display. A personal understanding

Image processing is based on the official Android Image fetcher processing. Universal-imageloader added a level two cache mechanism (memory +disk). For the decode option parameter configuration, the loading process of state processing, etc. have added their own a lot of understanding. The source of the daytime, there will be no small harvest.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.