Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android圖片處理內存優化系列之圖片牆案例

Android圖片處理內存優化系列之圖片牆案例

編輯:關於Android編程

本篇文章的主要內容是說圖片的內存緩存和從網絡異步獲取圖片的過程

工程效果圖如下:
這裡寫圖片描述vcq9o6zU2rG+tdjDu9PQu7q05qOs0rLDu9PQttTNvMasvfjQ0NG5y/W7r6OouvPG2tTZ1/bV4tCpstnX96OpoaM8L3A+DQo8cD7K18/Iv7S0+sLro6xNYWluQWN0aXZpdHm1xLK8vtbOxLz+IGFjdGl2aXR5X21haW4ueG1sIMjnz8I8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;">

代碼中部分不常見的屬性解釋如下(百度也可以找到的)

android:numColumns="auto_fit"  意思是圖片牆分成幾列  :auto_fit自適應

android:stretchMode="columnWidth" 圖片牆右邊多出來或者少的區域適配方式:在列寬上進行加減來適配

同時給GridView適配的adapter的View的布局文件 view_photo.xml如下



    

布局文件很簡單,接下來就是解決圖片源的問題,我這裡使用的是本地的tomcat服務器,將圖片保存在本地的tomcat服務器上,自己定義好鏈接來進行訪問:

tomcat上的文件如圖:
這裡寫圖片描述

圖片的鏈接類如下:

package com.jishihuitong.photowalldemo;

/**
 * Created by hss on 2016/7/27.
 */
public class Images {
    public static final String[] IMAGE = new String[]{
            "http://10.0.2.2:8080/images/01.png",
            "http://10.0.2.2:8080/images/02.png",
            "http://10.0.2.2:8080/images/03.png",
            "http://10.0.2.2:8080/images/04.png",
            "http://10.0.2.2:8080/images/05.png",
            "http://10.0.2.2:8080/images/06.png",
            "http://10.0.2.2:8080/images/07.png",
            "http://10.0.2.2:8080/images/08.png",
            "http://10.0.2.2:8080/images/09.png",
            "http://10.0.2.2:8080/images/10.png",
            "http://10.0.2.2:8080/images/11.png",
            "http://10.0.2.2:8080/images/12.png",
            "http://10.0.2.2:8080/images/13.png",
            "http://10.0.2.2:8080/images/14.png",
            "http://10.0.2.2:8080/images/15.png",
            "http://10.0.2.2:8080/images/16.png",
            "http://10.0.2.2:8080/images/17.png",
            "http://10.0.2.2:8080/images/18.png",
            "http://10.0.2.2:8080/images/19.png",
            "http://10.0.2.2:8080/images/20.png",
            "http://10.0.2.2:8080/images/21.png",
            "http://10.0.2.2:8080/images/22.png",
            "http://10.0.2.2:8080/images/23.png",
            "http://10.0.2.2:8080/images/24.png",
            "http://10.0.2.2:8080/images/25.png",
            "http://10.0.2.2:8080/images/26.png",
            "http://10.0.2.2:8080/images/27.png",
            "http://10.0.2.2:8080/images/28.png",
            "http://10.0.2.2:8080/images/29.png",
            "http://10.0.2.2:8080/images/30.png",
            "http://10.0.2.2:8080/images/31.png",
            "http://10.0.2.2:8080/images/32.png",
            "http://10.0.2.2:8080/images/33.png",
            "http://10.0.2.2:8080/images/34.png",
            "http://10.0.2.2:8080/images/35.png",
            "http://10.0.2.2:8080/images/36.png",
            "http://10.0.2.2:8080/images/37.png",
            "http://10.0.2.2:8080/images/38.png",
            "http://10.0.2.2:8080/images/39.png",
            "http://10.0.2.2:8080/images/40.png",
            "http://10.0.2.2:8080/images/41.png",
            "http://10.0.2.2:8080/images/42.png",
            "http://10.0.2.2:8080/images/43.png",
            "http://10.0.2.2:8080/images/44.png",
            "http://10.0.2.2:8080/images/45.png",
            "http://10.0.2.2:8080/images/46.png",
            "http://10.0.2.2:8080/images/47.png",
            "http://10.0.2.2:8080/images/48.png",
            "http://10.0.2.2:8080/images/49.png",
            "http://10.0.2.2:8080/images/50.png",
            "http://10.0.2.2:8080/images/51.png",
            "http://10.0.2.2:8080/images/52.png",
            "http://10.0.2.2:8080/images/53.png",
            "http://10.0.2.2:8080/images/54.png",
            "http://10.0.2.2:8080/images/55.png",
            "http://10.0.2.2:8080/images/56.png",
            "http://10.0.2.2:8080/images/67.png",
            "http://10.0.2.2:8080/images/58.png",
            "http://10.0.2.2:8080/images/59.png",
            "http://10.0.2.2:8080/images/60.png",
            "http://10.0.2.2:8080/images/61.png",
            "http://10.0.2.2:8080/images/62.png",
            "http://10.0.2.2:8080/images/63.png",
            "http://10.0.2.2:8080/images/64.png",
            "http://10.0.2.2:8080/images/65.png",
            "http://10.0.2.2:8080/images/66.png",
            "http://10.0.2.2:8080/images/67.png",
            "http://10.0.2.2:8080/images/68.png",
            "http://10.0.2.2:8080/images/69.png",
            "http://10.0.2.2:8080/images/70.png",
            "http://10.0.2.2:8080/images/71.png",
            "http://10.0.2.2:8080/images/72.png",
            "http://10.0.2.2:8080/images/73.png",
            "http://10.0.2.2:8080/images/74.png",
            "http://10.0.2.2:8080/images/75.png",
            "http://10.0.2.2:8080/images/76.png",
            "http://10.0.2.2:8080/images/77.png",
            "http://10.0.2.2:8080/images/78.png"
    };
}

再來看MainActivity裡面的代碼:

package com.jishihuitong.photowalldemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;

public class MainActivity extends AppCompatActivity {

    /**
     * 圖片牆GridView的適配器Adapter
     */
    private PhotoWallAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView photowall = (GridView) findViewById(R.id.gv_photowall);
        adapter = new PhotoWallAdapter(getApplicationContext(),0, Images.IMAGE,photowall);
        photowall.setAdapter(adapter);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //activity退出的時候取消所有正在下載的圖片任務
        adapter.cancelAllTasks();
    }
}

主要的思路是photoWallAdapter繼承ArrayAdapter重寫裡面的getView方法,將View加載進去,

1、在構造方法中把GridView對象傳進來,便於引用
2、首先在Adapter的構造方法裡面實例化Lrucache對象,
3、實例化任務集合,實例化任務BitmapWorkerTask參數是String類型的,返回值是Bitmap類型的
4、給GridView設置滾動監聽,當第一次進入app的時候,把屏幕上出現的所有的圖片都加載出來,當不是第一次進入的時候,判斷是滾動狀態還是停止狀態,只有在停止狀態的時候才去加載圖片,滾動狀態下取消所有的下載圖片任務
5、下載完圖片之後給保存到內存中

具體過程見代碼:

MainActivity裡面沒有多少代碼,最主要的 看這個PhotoWallAdapter

package com.jishihuitong.photowalldemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;

/**
 * Created by hss on 2016/7/27.
 */
public class PhotoWallAdapter extends ArrayAdapter {
    /**
     * GridView實例
     */
    private GridView mGridView;
    /**
     * 圖片內存緩存類
     */
    private LruCache mLruCache;
    /**
     * 任務管理集合
     */
    private HashSet mTaskCollection;

    private View view;
    /**
     * 第一個可以看見的條目下標
     */
    private int mFirstVisibleItem;
    /**
     * 可以看見的條目總數
     */
    private int mVisibleItemCount;
    /**
     * 是否是第一次進入
     */
    private boolean isFirstEnter = true;
    /**
     * 全局tag標記
     */
    private static final String TAG = "PhotoWallAdapter";
    public PhotoWallAdapter(Context context, int resource, String[] objects, GridView gridView) {
        super(context, resource, objects);
        this.mGridView = gridView;
        //獲取到當前系統的最大內存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //我們使用最大內存的1/8作為本應用緩存圖片的空間大小
        int cacheMemory = maxMemory / 8;
        //創建內存緩存對象,參數為定義好的緩存大小,
        mLruCache = new LruCache(cacheMemory) {
            //重寫sizeOf()方法,默認返回圖片的數量
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount();
            }
        };
        //實例化任務集合
        mTaskCollection = new HashSet();
        //給gridView設置滾動監聽
        mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
            //開始滾動的時候,取消下載任務,
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                //成員變量隨著滾動而變化
                mFirstVisibleItem = firstVisibleItem;
                mVisibleItemCount = visibleItemCount;
                //如果第一次進來的時候,滑動狀態下可以加載圖片,
                if(isFirstEnter && visibleItemCount>0){
                    //加載可見范圍內全部的圖片
                    loadBitmaps(firstVisibleItem,visibleItemCount);
                    isFirstEnter = false;
                }
            }
            //處於不滾動狀態的時候,再開始任務
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if(scrollState== AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
                    LogUtil.d(TAG,"mFirstVisibleItem = "+mFirstVisibleItem+"  mVisibleItemCount = "+mVisibleItemCount);
                    loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
                }else{
                    //取消所有的下載圖片的任務
                    cancelAllTasks();
                }
            }
        });
    }

    /**
     * 取消所有下載圖片的任務
     */
    public void cancelAllTasks() {
        if(mTaskCollection!=null){
            for (BitmapWorkerTask task: mTaskCollection) {
                task.cancel(false);
            }
        }
    }

    /**
     * 定義任務,執行任務,選擇方法從本地和網絡上加載圖片
     * @param firstVisibleItem gridView中可以看見的第一個角標
     * @param visibleItemCount gridView中可以看見的所有圖片的總數
     */
    private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
        try{
            for (int i = firstVisibleItem; i  {


        private String imageUrl;
        //需要在後台進程中干的事情
        @Override
        protected Bitmap doInBackground(String... params) {
            //從參數中獲取到傳進來的圖片URL
            imageUrl = params[0];
            //從網絡上下載圖片
            Bitmap bitmap = downLoadBitmap(params[0]);
            //如果下載到的圖片不為空,把圖片保存進內存中
            if(bitmap!=null){
                addBitmapToCacheMemory(params[0],bitmap);
            }
            return bitmap;
        }
        //該方法在上面的方法,DoInBackground之後運行,方法裡面的參數就是上面的方法的返回值
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            ImageView photo = (ImageView) mGridView.findViewWithTag(imageUrl);
            if(bitmap!=null&&photo!=null){
                photo.setImageBitmap(bitmap);
            }
            //完了記得把任務清除掉
            mTaskCollection.remove(this);
        }

        /**
         * 從網絡上下載圖片,在後台進程中運行
         * @param imageUrl
         * @return
         */
        private Bitmap downLoadBitmap(String imageUrl) {
            Bitmap bitmap = null;
            HttpURLConnection conn = null;
            try{
                URL url = new URL(imageUrl);
                conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5*1000);
                conn.setReadTimeout(10 * 1000);
                conn.setDoInput(true);
                conn.setDoOutput(true);
                bitmap = BitmapFactory.decodeStream(conn.getInputStream());
            }catch(Exception e){
                e.printStackTrace();
            }finally {
                if(conn!=null){
                    conn.disconnect();
                }
            }
            return bitmap;
        }

    }

}

運行的時候別忘了在清單文件中添加連接網絡的權限

下載源碼

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved