Android Photo Wall application to achieve no more pictures are not afraid to crash _android

Source: Internet
Author: User
Tags http request network function xmlns

Photo wall This kind of function is quite common now, in many applications you can often see the shadow of the picture wall. Its design is actually very simple, with a GridView control as a "wall", and then along with the GridView rolling a picture affixed to the "wall", these photos can be stored on the phone locally, can also be downloaded from the Internet. To make an application similar to this one, there is a very important question to consider when the picture resources should be released. Because with the GridView scrolling, the load of pictures may be more and more, if there is no reasonable mechanism for the release of the picture, then when the picture reached a certain limit, the program will inevitably crash.

Today, the implementation of our photo wall application focuses on how to prevent the program from collapsing because of too many pictures. The main core algorithm uses the LRUCache class provided in Android, which is provided in version 3.1, and you need to import a ANDROID-SUPPORT-V4 jar package if you are developing it in an earlier version of Android.
For detailed explanation of LRUCache usage, you can refer to the Android high efficient loading and mapping scheme to effectively avoid program oom.

So let's start with a new Android project called Photowalldemo, where I'm using the Android 4.0 API.

The first question to consider is, where do we collect so many pictures? Here I have from Google's official demo to take out the image source, we will download the images from these URLs, the code is as follows:

public class Images {public 
 
  final static string[] Imagethumburls = new string[] {  
       "https://lh4.googleusercontent . Com/-vngkd5z1u8w/urqvjucegpi/aaaaaaaaabs/ulxcmvcu6eu/s160-c/valley%252520sunset.jpg ", 
      " https:// Lh6.googleusercontent.com/-doz5i2e2omq/urqvkmnd1ki/aaaaaaaaabs/iqf0isinleo/s160-c/windmill%252520sunrise.jpg ", 
      "Https://lh5.googleusercontent.com/-biyiyWcJ9MU/URqvKculiAI/AAAAAAAAAbs/jyPsCplJOpE/s160-c/Windmill.jpg", 
      "Https://lh4.googleusercontent.com/-PDT167_xRdA/URqvK36mLcI/AAAAAAAAAbs/oi2ik9QseMI/s160-c/Windmills.jpg" , 
      "https://lh5.googleusercontent.com/-kI_QdYx7VlU/URqvLXCB6gI/AAAAAAAAAbs/N31vlZ6u89o/s160-c/Yet% 252520another%252520rockaway%252520sunset.jpg ", 
      " https://lh4.googleusercontent.com/-e9NHZ5k5MSs/ Urqvmibzjti/aaaaaaaaabs/1fv810rdnfq/s160-c/yosemite%252520tree.jpg ",}; 
} 

The source of the picture is already there, and now we should consider where to place the pictures. New or open Activity_main.xml as the main layout of the program, add the following code:

<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" 
  xmlns:tools= "http:// Schemas.android.com/tools " 
  android:layout_width=" wrap_content " 
  android:layout_height=" Wrap_content " > 
   
  <gridview  
    android:id= "@+id/photo_wall" 
    android:layout_width= "Match_parent" 
    android: layout_height= "Wrap_content" 
    android:columnwidth= "90dip" 
    android:stretchmode= "ColumnWidth" 
    android:numcolumns= "Auto_fit" 
    android:verticalspacing= "10dip" 
    android:gravity= "center" 
    >< /gridview> 
   
</LinearLayout> 

As you can see, we've only added a GridView to this layout file, which is the "wall" in our program, and all the pictures will be posted on this "wall".
We then define the layout of each child view in the GridView, create a new Photo_layout.xml layout, and add the following code:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" 
  xmlns:tools= "http:// Schemas.android.com/tools " 
  android:layout_width=" wrap_content " 
  android:layout_height=" Wrap_content " > 
 
  <imageview  
    android:id= "@+id/photo" 
    android:layout_width= "90dip" 
    android:layout_height= "90dip" 
    android:src= "@drawable/empty_photo" 
    android:layout_centerinparent= "true" 
    /> 
 
</ Relativelayout> 

In each child view we simply use a imageview to display a picture. So all the layouts are already defined.
Next, create a new Photowalladapter as the GridView adapter, as shown in the following code:

public class Photowalladapter extends arrayadapter<string> implements Onscrolllistener {/** * record all downloads or waits 
   Download the task. 
 
  * * Private set<bitmapworkertask> taskcollection; 
   /** * Image caching Technology's core class, used to cache all downloaded pictures, when the program memory reaches the set value will be the least recently used pictures removed. 
 
  * Private lrucache<string, bitmap> Mmemorycache; 
 
  /** * The example of the GridView */private GridView Mphotowall; 
 
  /** * The first visible picture of the subscript * * * private int mfirstvisibleitem; 
 
  /** * A screen of how many pictures visible * * * private int mvisibleitemcount; 
   /** * Record whether the program has just been opened to solve the entry program does not scroll the screen, will not download pictures of the problem. 
 
  * Private Boolean isfirstenter = true; Public Photowalladapter (context context, int Textviewresourceid, string[] objects, GridView photowall) {Super 
    (Context, Textviewresourceid, objects); 
    Mphotowall = Photowall; 
    Taskcollection = new hashset<bitmapworkertask> (); 
    Gets the application's maximum available memory int maxmemory = (int) runtime.getruntime (). MaxMemory (); 
    int cacheSize = MAXMEMORY/8; //Set the picture cache size to the program's maximum available memory 1/8 Mmemorycache = new lrucache<string, bitmap> (cacheSize) {@Override protecte 
      d int sizeOf (String key, Bitmap Bitmap) {return bitmap.getbytecount (); 
    } 
    }; 
  Mphotowall.setonscrolllistener (this); @Override public View getview (int position, View Convertview, ViewGroup parent) {final String URL = getite 
    m (position); 
    View view; 
    if (Convertview = = null) {view = Layoutinflater.from (GetContext ()). Inflate (r.layout.photo_layout, NULL); 
    else {view = Convertview; 
    Final ImageView photo = (ImageView) View.findviewbyid (R.id.photo); 
    Set a tag to ImageView to ensure that the picture will not be randomly loaded photo.settag (URL); 
    Setimageview (URL, photo); 
  return view; /** * Set picture for ImageView. First remove the cache of the picture from the LRUCache and set it to the ImageView. 
   If the picture is not cached in LRUCache, set a default picture for ImageView. 
   * * @param imageUrl * The URL of the picture, used as the LRUCache key. 
   * @param ImageView * Controls that are used to display pictures. */ 
  private void Setimageview (String imageUrl, ImageView imageview) {Bitmap Bitmap = Getbitmapfrommemorycache (imageu 
    RL); 
    if (bitmap!= null) {Imageview.setimagebitmap (bitmap); 
    else {imageview.setimageresource (R.drawable.empty_photo); 
   }/** * Stores a picture in LRUCache. 
   * @param key * LRUCache, where the URL address of the image is passed in. 
   * @param bitmap * LRUCache key, where bitmap objects downloaded from the network are passed in. 
      */public void Addbitmaptomemorycache (String key, Bitmap Bitmap) {if (Getbitmapfrommemorycache (key) = null) { 
    Mmemorycache.put (key, bitmap); 
   }/** * Gets a picture from the LRUCache and returns null if it does not exist. 
   * @param key * LRUCache, where the URL address of the image is passed in. 
   * @return The Bitmap object that corresponds to the incoming key, or null. 
  * * Public Bitmap Getbitmapfrommemorycache (String key) {return mmemorycache.get (key); @Override public void onscrollstatechanged (Abslistview view, int scrollstate) {//download pictures only when the GridView is still static, Grid Cancel all downloaded tasks while view is slidingF (scrollstate = = Scroll_state_idle) {loadbitmaps (Mfirstvisibleitem, Mvisibleitemcount); 
    else {cancelalltasks (); @Override public void Onscroll (Abslistview view, int firstvisibleitem, int visibleitemcount, int tot 
    Alitemcount) {mfirstvisibleitem = Firstvisibleitem; 
    Mvisibleitemcount = VisibleItemCount; 
    The downloaded task should be called by onscrollstatechanged, but onscrollstatechanged will not be invoked when the program is first entered,//So here for the first entry program to open the download task. 
      if (isfirstenter && visibleitemcount > 0) {loadbitmaps (Firstvisibleitem, VisibleItemCount); 
    Isfirstenter = false; }/** * Loads the bitmap object. 
   This method examines the ImageView bitmap objects visible in all screens in LRUCache, and if any ImageView bitmap object is found not in the cache, an asynchronous thread is opened to download the picture. 
  * * @param firstvisibleitem * The first visible imageview subscript * @param The total number of elements visible in the visibleitemcount * screen * *  private void Loadbitmaps (int firstvisibleitem, int visibleitemcount) {try {for (int i = Firstvisibleitem; I &LT Firstvisibleitem + visibleitemcount; 
        i++) {String imageUrl = images.imagethumburls[i]; 
        Bitmap Bitmap = Getbitmapfrommemorycache (IMAGEURL); 
          if (bitmap = = null) {Bitmapworkertask task = new Bitmapworkertask (); 
          Taskcollection.add (Task); 
        Task.execute (IMAGEURL); 
          else {ImageView ImageView = (imageview) mphotowall.findviewwithtag (IMAGEURL); 
          if (ImageView!= null && bitmap!= null) {Imageview.setimagebitmap (bitmap); 
    catch (Exception e) {e.printstacktrace ()}}}; 
   }/** * Cancels all tasks that are downloading or waiting to be downloaded. */public void Cancelalltasks () {if (taskcollection!= null) {for (Bitmapworkertask task:taskcollection 
      ) {Task.cancel (false); 
   }}/** * The task of downloading pictures asynchronously. * * @author Guolin/class Bitmapworkertask extends Asynctask<string, Void, bitmap> {/** * The URL address of the picture/private String imageUrl; 
      @Override protected Bitmap doinbackground (String ... params) {imageUrl = params[0]; 
      Start downloading pictures in the background Bitmap Bitmap = Downloadbitmap (Params[0]); 
      if (bitmap!= null) {//Picture download is complete after caching to Lrccache Addbitmaptomemorycache (params[0), bitmap); 
    return bitmap; 
      } @Override protected void OnPostExecute (Bitmap Bitmap) {super.onpostexecute (BITMAP); 
      According to the tag to find the appropriate ImageView control, will download a good picture display. 
      ImageView ImageView = (imageview) mphotowall.findviewwithtag (IMAGEURL); 
      if (ImageView!= null && bitmap!= null) {Imageview.setimagebitmap (bitmap); 
    } taskcollection.remove (this); 
     /** * establishes an HTTP request and obtains the bitmap object. * * @param imageUrl * Image URL Address * @return resolved Bitmap object/Private Bitmap Downloadbitmap (S 
      Tring imageUrl) {Bitmap Bitmap = null; HttpURLConnection con = Null 
        try {URL url = new URL (imageUrl); 
        Con = (httpurlconnection) url.openconnection (); 
        Con.setconnecttimeout (5 * 1000); 
        Con.setreadtimeout (10 * 1000); 
      Bitmap = Bitmapfactory.decodestream (Con.getinputstream ()); 
      catch (Exception e) {e.printstacktrace (); 
        finally {if (con!= null) {con.disconnect (); 
    } return bitmap; 
 } 
 
  } 
 
}

Photowalladapter is one of the most critical classes in the entire photo-wall program, and here's what I'd like to focus on. First, in the Photowalladapter constructor, we initialize the LRUCache class and set the maximum cache capacity to 1/8 of the maximum available memory for the program, and then register a scrolling listener for the GridView. Then in the GetView () method, we set a unique tag for each imageview, the role of this tag is to be able to accurately retrieve the ImageView, or the asynchronous loading of the picture will appear chaos sequence. The Setimageview () method is then invoked to set a picture for ImageView, which first looks in the LRUCache cache to see if the picture has been cached, and if it is successfully found, the picture in the cache is displayed on the ImageView. Otherwise, a default empty picture is displayed.

Read for a long time, that is where to download the picture? This is done in the GridView scrolling listener, in the Onscrollstatechanged () method, we judge the scroll state of the GridView, and call Loadbitmaps () if the current GridView is static. method to download the picture, if the GridView is scrolling, cancel all download tasks so that the GridView scrolling flow is guaranteed. In the Loadbitmaps () method, we open a thread for all visible GridView child elements on the screen to perform the download task, store the picture in the LRUCache after the successful download, and then find the corresponding ImageView control by tag. Show the downloaded pictures.

Because we use LRUCache to cache pictures, we do not need to worry about the memory overflow situation, when the total size of the image stored in the LRUCache reached the upper limit of the capacity, will automatically remove the most recently used pictures from the cache.
Finally, create or open mainactivity as the main activity for the program, as shown in the following code:

The public class Mainactivity extends activity { 
 
  /** 
   * is used to display the photo wall of the GridView * * 
  private gridview Mphotowall; 
 
  /** 
   * GridView Adapter * 
   * 
  private photowalladapter adapter; 
 
  @Override 
  protected void onCreate (Bundle savedinstancestate) { 
    super.oncreate (savedinstancestate); 
    Setcontentview (r.layout.activity_main); 
    Mphotowall = (GridView) Findviewbyid (r.id.photo_wall); 
    adapter = new Photowalladapter (this, 0, Images.imagethumburls, mphotowall); 
    Mphotowall.setadapter (adapter); 
  } 
 
  @Override 
  protected void OnDestroy () { 
    Super.ondestroy (); 
    End all download tasks when exiting the program 
    adapter.cancelalltasks (); 
  } 
 
 

The code in Mainactivity is very simple, there is nothing to be explained, when the activity is destroyed, cancel all the download tasks, avoid the program in the background to drain traffic. In addition, because we use the network function, do not forget to add the Network permission statement in the Androidmanifest.xml.
Now you can run the program, the effect shown in the following figure:


As you can see, scrolling the photo wall will asynchronously load the picture onto the corresponding ImageView. As the loading of the picture increases, you will be able to release some of the previously loaded pictures, you can scroll a few times to see. In addition, I did not use the local cache in this program in order to make it obvious that the picture was released, and all the released pictures were again shown to be downloaded again from the network. It would be better to match the appropriate local caching effect in the actual project.
Open Ddms, we can find that, because there are lrucache to help us manage the image cache, no matter how the photo wall scrolling, program memory will always remain within a reasonable range.

The focus of this article is on how to better recycle pictures, so the photo wall is simply using the GridView to show that the friend who wants to see a cooler, more stunning picture wall effect, can refer to an article in the back of my Android waterfall stream photo wall to realize, experience the beauty of irregular arrangement.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

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.