Retrofit2+executors+disklrucache 2 seconds to load 100 pictures from the trouble of Oom

Source: Internet
Author: User

The journey of life, the future is very far, also very dark. However, do not be afraid, not afraid of the people before the road. --Lu Xun

Since the last blog post, has been a long time not updated blog, has been busy to pay the things, here to apologize to everyone.

Put a picture first:

Do not be surprised, this is the first time to get pictures from the network speed, feel more than the speed of local reading of the picture is faster. Load 100 pictures really just 2 seconds, you do not believe, do not trust you to see.

I. Overview

In many app , the cache can be used as a measure of the quality of a product, both to save traffic, reduce power consumption, the most important is the user experience good. Would you like to use a product 100M that consumes more of your traffic per month? Of course there is nothing but games. So how do you cache it? Here to introduce two important concepts, one is the memory cache LruCache , one is the hard disk cache DiskLruCache , we are certainly not unfamiliar with these two concepts, if you do not understand the words please link Guo Shen android Disklrucache full Parse, The best solution for hard disk caching It's really good to write. It can be seen from the title that today there is a thread pool that is the concept I have heard a long time ago, but not specifically to study, I will only use it.

Related articles Please link the address:

Retrofit2 and Rxjava usage analysis

Understanding and using the thread pool in Android

Android Disklrucache full parsing, hard disk caching best practices

Second, executors probe into thread pool

Android commonly used thread pool has the following several, in the Executors corresponding method:

    1. Newfixedthreadpool each time a thread pool is executed with a limited number of tasks
    2. Newcachedthreadpool thread pool where all tasks are started at once
    3. Newsinglethreadexecutor thread pool that executes only one task at a time
    4. Newscheduledthreadpool creates a thread pool that can perform tasks at a specified time, and can be executed repeatedly

To get an instance:

Executors.newSingleThreadExecutor();// 每次只执行一个线程任务的线程池Executors.newFixedThreadPool(3);// 限制线程池大小为3的线程池// 一个没有限制最大线程数的线程池Executors.newScheduledThreadPool(3);// 一个可以按指定时间可周期性的执行的线程池

Let's take a look at the following example:

new Thread(new Runnable() {           @Override           publicvoidrun() {           }       }).start();

Functionally equivalent to:

        mMyHandler.post(new Runnable() {            @Override            publicvoidrun() {            }        });

Also equivalent to:

        executors.execute(new Runnable() {            @Override            publicvoidrun() {            }        });

Why should we use ExecutorService it instead of using Thread and Handler ? Using thread pooling I think it's important to follow up on threads that we've turned on, to be able to reuse this, to reduce memory consumption, and of course to specify the number of thread pools that perform tasks, and create a pool of threads that can perform tasks at a specified time.

Thread pool Usage

Three, Disklrucache simple introduction

If you would like more information, please link to the relevant article.

Note: Depending on the package in your project retrofit , the DiskLruCache class is included, so you can avoid repeating the guide.

First look at DiskLruCache The example method:

publicstaticopenintintlong maxSize)  

open()The method receives four parameters, the first parameter specifies the cached address of the data, the second parameter specifies the version number of the current application, the third parameter specifies how many cache files the same key can correspond to, the basic is 1, and the fourth parameter specifies the maximum number of bytes of data that can be cached, so I will not repeat the explanation here. Please see the related articles link.

Let's take a look at the beginning of the article how to quickly load out the image of the program is how to achieve. I try to make the picture load so fast, still quite excited.

1. XML layout
    <ListView        android:id="@+id/lv"        android:layout_width="match_parent"        android:layout_height="match_parent">    </ListView>

Just one ListView , there's nothing to say.

2. Activity file
        lv= (ListView) findViewById(R.id.lv);        mAdapter=new TestAdapter(Images.imageThumbUrls,R.layout.photo_layout,this,lv);        lv.setAdapter(mAdapter);

is a more general wording, here Adapter the main argument:

publicTestAdapterint layoutId, Context context, ViewGroup view)

The first parameter represents an array of picture addresses
The second parameter represents a sub-layout Id
The third parameter represents a context context
The fourth parameter represents the current one ListView , and the request network is asynchronously loaded to prevent picture dislocation

3. Adapter File

Member variables:

   /** * A core class of image caching technology that caches all downloaded images and removes the least recently used images when the program memory reaches the set value. */    PrivateLrucache<string, bitmap> Mmemorycache;/** * Picture hard disk Cache core class. */    PrivateDisklrucache Mdisklrucache;/** * thread pool Download Picture * *    PrivateExecutorservice executors;PrivateString[] datas;//Data source    Private intLayoutID;//Layout ID    PrivateContext Mcontext;//Context    PrivateViewGroup Mviewgroup;//corresponding to the ListView    PrivateMyHandler Mmyhandler;//hanler

The corresponding initialization:

     Public Testadapter(string[] Datas,intLayoutID, Context context, ViewGroup view) { This. datas = datas; This. LayoutID = LayoutID;        Mcontext = context; Mviewgroup = view;//taskcollection = new hashset<bitmapworkertask> ();        //Get the maximum available memory for the application        intMaxMemory = (int) Runtime.getruntime (). MaxMemory ();intCacheSize = maxmemory/8;//Set the picture cache size to the 1/8 of the program's maximum available memoryMmemorycache =NewLrucache<string, bitmap> (cacheSize) {@Override            protected int sizeOf(String key, Bitmap Bitmap) {returnBitmap.getbytecount (); }        };Try{//Get Picture cache pathFile Cachedir = Getdiskcachedir (Context,"Bitmap");if(!cachedir.exists ())            {Cachedir.mkdirs (); }//Create Disklrucache instance, initialize cache dataMdisklrucache = disklrucache. Open (Cachedir, getappversion (context),1, -*1024x768*1024x768); }Catch(IOException e)        {E.printstacktrace (); } executors = Executors.newfixedthreadpool (3); Mmyhandler =NewMyHandler ( This); }

Next look at the getView method:

    @Override    publicgetView(int position, View convertView, ViewGroup parent) {        String url = (String) getItem(position);        View view;        ifnull) {            view = LayoutInflater.fromnull);        else {            view = convertView;        }        ImageView imageView = (ImageView) view.findViewById(R.id.photo);        imageView.setTag(url);//防止图片错位        imageView.setImageResource(R.drawable.empty_photo);        loadBitmaps(imageView, url);        return view;    }

loadBitmapsMethod:

 public   void  loadbitmaps  (ImageView ImageView, String imageUrl) {try  {Bitmap Bitmap = Getbitmapfrommemorycache (IMAGEURL); if  (Bitmap = = null )            {Startexecutor (IMAGEURL); } else  {if  (ImageView! = null  && Bitmap! = null ) {Imageview.seti                Magebitmap (bitmap);        }}} catch  (Exception e) {e.printstacktrace (); }    }

Loads the Bitmap object. This method LruCache checks all the visible objects in the screen, ImageView and Bitmap if any ImageView of the objects are found Bitmap not in the cache, then it is then checked to see if it is LruCache Bitmap in DiskLruCache , and if not, open the asynchronous thread to download the picture. Instead, add them to the LRUCache and show them. The DiskLruCache file is converted into a Bitmap time-consuming operation that prevents the UI thread from incurring, so it takes place in the thread pool.

startExecutorHow is the method implemented:

     Public void Startexecutor(FinalString imageUrl) {Executors.execute (NewRunnable () {@Override             Public void Run() {FileDescriptor FileDescriptor =NULL; FileInputStream FileInputStream =NULL; Disklrucache.snapshot Snapshot =NULL;Try{//Generate image URL corresponding to key                    FinalString key = Hashkeyfordisk (IMAGEURL);//Find the corresponding cache for keySnapShot = Mdisklrucache.get (key);if(SnapShot = =NULL) {//If no corresponding cache is found, prepare to request data from the network and write to the cacheDisklrucache.editor Editor = Mdisklrucache.edit (key);if(Editor! =NULL) {OutputStream OutputStream = Editor.newoutputstream (0);if(Downloadurltostream (IMAGEURL, OutputStream))                            {Editor.commit (); }Else{Editor.abort (); }                        }after the cache is written, find the cache for key againSnapShot = Mdisklrucache.get (key); }if(SnapShot! =NULL) {FileInputStream = (FileInputStream) Snapshot.getinputstream (0);                    FileDescriptor = Fileinputstream.getfd (); }//Parse the cached data into a bitmap objectBitmap Bitmap =NULL;if(FileDescriptor! =NULL) {bitmap = Bitmapfactory.decodefiledescriptor (FileDescriptor); }if(Bitmap! =NULL) {//Add the bitmap object to the memory cacheAddbitmaptomemorycache (ImageUrl, bitmap); } mmyhandler.post (NewRunnable () {@Override                         Public void Run() {ImageView ImageView = (ImageView) mviewgroup.findviewwithtag (IMAGEURL); Bitmap Bitmap = Getbitmapfrommemorycache (IMAGEURL);if(ImageView! =NULL&& Bitmap! =NULL) {Imageview.setimagebitmap (bitmap);                }                        }                    }); }Catch(IOException e)                {E.printstacktrace (); }finally{if(FileDescriptor = =NULL&& FileInputStream! =NULL) {Try{Fileinputstream.close (); }Catch(IOException e)    {                        }                    }                }            }        }); }

The representative is longer and needs to be resistant to look.

Get Picture stream:

    /** * Establish an HTTP request and get the bitmap object. * * @param The URL address of the urlstring image * @return parsed Bitmap Object * *    Private Boolean Downloadurltostream(String urlstring, OutputStream outputstream) {HttpURLConnection URLConnection =NULL; Bufferedoutputstream out =NULL; Bufferedinputstream in =NULL; InputStream InputStream =NULL;Try{in =NewBufferedinputstream (NewURL (urlstring). OpenStream ()); out =NewBufferedoutputstream (OutputStream);intb while((b = In.read ())! =-1) {Out.write (b); }return true; }Catch(FinalIOException e) {e.printstacktrace (); }finally{if(URLConnection! =NULL) {urlconnection.disconnect (); }Try{if(Out! =NULL) {out.close (); }if(In! =NULL) {in.close (); }if(InputStream! =NULL) {inputstream.close (); }            }Catch(FinalIOException e) {e.printstacktrace (); }        }return false; }

The fastest new URL(urlString).openStream() way to get a picture stream has been tested. Here to get the stream can also be used retrofit :

        try {            ResponseBody responseBody = client.getRectService().downBitmaps(urlPath).execute().body();            ifnull) {                return responseBody.byteStream();//返回图片流            }        catch (IOException e) {            e.printStackTrace();        }

Because of retrofit some internal encapsulation, it is not recommended to get the stream for a long time.

You can also get flows like this:

            finalnew URL(urlString);            urlConnection = (HttpURLConnection) url.openConnection();            urlConnection.getInputStream();
Iv. Conclusion

The first time is the time to start loading the first picture

The second time is when the last picture is loaded

They have a timestamp of more than 2 seconds.

Take a look at monitors:

The source waiting to upload ... github

Retrofit2+executors+disklrucache 2 seconds to load 100 pictures from the trouble of Oom

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.