Android中listView中用於下載、顯示圖片

緩存—>SD卡—>網絡

ImageLoader

package com.example.jack.myapplication.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import android.widget.ImageView;

import com.example.jack.myapplication.R;
import com.example.jack.myapplication.consts.MyHttpURL;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 用於下載、顯示圖片
 * Created by ding on 2015/10/26.
 */
public class ImageLoader {

    //緩存
    private LruCache<String, Bitmap> mCaches;
    private String bitmapFileName ;
    //構造方法
    public ImageLoader() {
        //獲取最大可用內存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 4;
        mCaches = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //在每次存入緩存時調用,存入圖片大小
                return value.getByteCount();
            }
        };
    }

    //將圖片寫入緩存
    public void addBitmapToCache(String bitmapFileName, Bitmap bitmap) {
        //先判斷bitmap是否爲空
        if (getBitmapFromCache(bitmapFileName) == null) {
            mCaches.put(bitmapFileName, bitmap);
        }
    }

    //根據url獲得緩存的圖片
    public Bitmap getBitmapFromCache(String bitmapFileName) {
        if(bitmapFileName!=null){
            return mCaches.get(bitmapFileName);
        }else {
            return null ;
        }
    }

    /**
     * 通過url獲得圖片
     *
     * @param  urlString
     * @return
     */
    public Bitmap getBitmapFromURL(String urlString) {

        if(urlString.equals(MyHttpURL.IP+null)||urlString.equals(MyHttpURL.IP)){
         return null ;
        }

        Bitmap bitmap;
        InputStream is = null;
        URL url;
        try {
            url = new URL(urlString);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            Log.i("getBitmapFromURL參數url爲:",urlString);

            InputStream ins = connection.getInputStream();

            //緩衝流
            is = new BufferedInputStream(ins);

            //將is轉化爲bitmap
            bitmap = BitmapFactory.decodeStream(is);
            //添加網絡中下載的bitmap到緩存和本地sd卡
            addBitmapToCache(urlString,bitmap);
            addBitmapToFile(urlString,bitmap);
            //關閉連接
            connection.disconnect();
            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    File dir = null;
    /**
     * 將圖片文件寫入文件
     * @param url
     * @param bitmap
     */
    public void addBitmapToFile(String url,Bitmap bitmap){
        //Environment.getExternalStorageState()方法用於獲取SDCard的狀態,如果手機裝有SDCard,
        //並且可以進行讀寫,那麼方法返回的狀態等於Environment.MEDIA_MOUNTED
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

            FileOutputStream fos = null ;
            //創建根目錄文件對象
            if(dir == null){
                dir = new File("/mnt/sdcard/test/");
            }

            //如果根目錄文件對象不存在
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File bitmapFile = null ;
            //創建圖片文件對象
            if(bitmapFile == null){
                bitmapFile = new File("/mnt/sdcard/test/" +
                        url.substring(url.lastIndexOf("/") + 1));
            }
            //如果圖片文件對象不存在,則創建新的文件
            if (!bitmapFile.exists()) {
                try {
                    bitmapFile.createNewFile();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            try {
                if(fos == null ){
                    //得到文件輸出流
                    fos = new FileOutputStream(bitmapFile);
                }
                //將圖片文件寫進文件中
                bitmap.compress(Bitmap.CompressFormat.PNG , 100 , fos);
                fos.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * 通過AsyncTask顯示圖片:從緩存中找--->從本地文件中找--->從網絡中找
     * @param imageView
     * @param imageUrl
     */
    public void showImageByAsyncTask(ImageView imageView, String imageUrl) {

        int i = 0 ;
        //根據url構建圖片文件名
        bitmapFileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
        //從緩存中取名爲url的圖片
        Bitmap bitmap = getBitmapFromCache(bitmapFileName);
        Log.i("提示:","從緩存中得到的圖片"+bitmap);
        //如果緩存中沒有,則先從本地文件中找
        if (bitmap == null) {


            Log.i("提示:","SD卡中圖片的文件名"+bitmap);
            //創建根目錄文件對象
            if(dir == null){
                dir = new File("/mnt/sdcard/test/");
            }
            //得到文件列表
            File[] cacheFiles = dir.listFiles();
            Log.i("提示:","文件列表爲:"+cacheFiles);
            Log.i("提示:","文件列表的大小:"+cacheFiles.length);

            if (cacheFiles != null) {

                //逐一查找
                for (; i < cacheFiles.length; i++) {
                    //如果文件列表中存在與圖片文件名相同的文件,則跳出for循環
                    if (bitmapFileName.equals(cacheFiles[i].getName())) {
                        break;//跳出for循環
                    }
                }
                //如果i < cacheFiles.length,說明存在圖片文件
                if (i < cacheFiles.length) {
                    imageView.setImageBitmap(BitmapFactory.decodeFile("/mnt/sdcard/test/" + bitmapFileName));
                    Log.i("提示:", "顯示的圖片從SD卡中來");
                    //將SD卡的圖片放到緩存中
                    addBitmapToCache(bitmapFileName, BitmapFactory.decodeFile("/mnt/sdcard/test/" + bitmapFileName));
                    return;//跳出方法
                }else{
                    //如果文件列表都沒有,則從網絡中找
                    LessonsIconAsyncTask task = new LessonsIconAsyncTask(imageView);
                    //執行task
                    task.execute(imageUrl);
                }
            }
            //文件夾都不存在,則圖片也不存在
            else{
                //如果文件列表都沒有,則從網絡中找
                LessonsIconAsyncTask task = new LessonsIconAsyncTask(imageView);
                //執行task
                task.execute(imageUrl);
            }
        } else {
            //緩存中存在,則直接顯示圖片
            imageView.setImageBitmap(bitmap);
            Log.i("提示:","顯示的圖片從緩存中來");
        }
    }

    /**
     * 自定義的AsyncTask,傳進的類型、返回過程、返回的類型
     */
    private class LessonsIconAsyncTask extends AsyncTask<String, Void, Bitmap> {
        private ImageView mImageView ;
        //構造方法
        private LessonsIconAsyncTask(ImageView imageView) {
            mImageView = imageView ;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //圖片url
            String url = params[0];
            //從網絡中獲取圖片
            Bitmap bitmap = getBitmapFromURL(url);
            //如果從網絡中獲得的圖片不爲空
            if (bitmap != null) {  //  1、將圖片寫入緩存 2、將圖片寫入文件
                //將圖片以url爲標誌寫入緩存
                addBitmapToCache(bitmapFileName, bitmap);
                //將圖片寫入文件
                addBitmapToFile(bitmapFileName, bitmap);
            }
            return bitmap;
        }

        //上面doInBackground返回的bitmap在這裏處理
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //如果該imageView不爲空且bitmap不爲空
            if (mImageView != null && bitmap != null) {
                //imageView顯示圖片
                mImageView.setImageBitmap(bitmap);
                Log.i("提示:", "顯示的圖片從網絡中來");
            }else {
                mImageView.setImageResource(R.mipmap.no);
                Log.i("提示:", "顯示的圖片爲默認圖片");
            }
        }
    }

}

LessonListAdapter

package com.example.jack.myapplication.adapter;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.example.jack.myapplication.R;
import com.example.jack.myapplication.entity.Lesson;
import com.example.jack.myapplication.utils.ImageLoader;

import java.util.List;


/**
 * listView的適配器
 * Created by ding on 2015/10/13.
 */
public class LessonListAdapter extends BaseAdapter {

    //保存所有需要顯示的圖片的url地址
    public String[] imageUrls;
    //數據源:課程信息集合
    List<Lesson> lessons;
    //運行上下文
    private Context context;
    //視圖容器
    private LayoutInflater inflater;
    //圖片下載的工具類
    private ImageLoader mImageLoader;

    //構造方法
    public LessonListAdapter(Context context, List<Lesson> lessons, ListView listView) {
        //並設置上下文
        this.context = context;
        //創建視圖容器
        inflater = LayoutInflater.from(context);
        //數據源
        this.lessons = lessons;

        imageUrls = new String[lessons.size()];
        for (int i = 0; i < lessons.size(); i++) {
            //將圖片url保存到該數組裏面
            imageUrls[i] = lessons.get(i).getLIcon();
        }
        //初始化ImageLoader,加載顯示圖片的工具類,將listview傳進去
        mImageLoader = new ImageLoader();
    }

    // 在此適配器中所代表的數據集中的條目數
    public int getCount() {
        return lessons.size();
    }

    //獲取數據集中與指定索引對應的  數據項
    public Object getItem(int position) {
        return lessons.get(position);
    }

    //取在列表中與指定索引對應的行id
    public long getItemId(int position) {
        return position;
    }

    /*
    ListView Item設置  :獲取一個在數據集中指定索引的視圖來顯示數據
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //控件集
        ViewHolder holder = null;
        //如果緩存convertView爲空,則需要創建View
        if (convertView == null) {
            //實例化控件集
            holder = new ViewHolder();
            //獲取list_item佈局文件的視圖  : 根據自定義的Item佈局加載佈局
            convertView = inflater.inflate(R.layout.lesson_item, null);

            //獲取控件對象
            holder.ivLessonIcon = (ImageView) convertView.findViewById(R.id.ivLessonIcon);
            holder.tvLessonName = (TextView) convertView.findViewById(R.id.tvLessonName);
            holder.tvLessonSectionNumber = (TextView) convertView.findViewById(R.id.tvLessonSectionNumber);

            //將設置好的佈局保存到緩存(convertView )中,並將其設置在Tag裏,以便後面方便取出Tag
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Lesson lesson = (Lesson) getItem(position);

        //圖片url
        String url = lesson.getLIcon();
        Log.i("提示:", "圖片url爲:" + url);
        //調用mImageLoader中的showImageByAsyncTask方法加載並顯示圖片
        mImageLoader.showImageByAsyncTask(holder.ivLessonIcon, url);
        holder.tvLessonName.setText(lesson.getLName());
        holder.tvLessonSectionNumber.setText(lesson.getLCount() + " 人學習");

        return convertView;
    }

    //自定義控件集合 :優化性能,按需填充並重新使用view來減少對象的創建。
    class ViewHolder {
        private ImageView ivLessonIcon;//課程圖標
        private TextView tvLessonName;//課程標題
        private TextView tvLessonSectionNumber;//課程學習人數
    }


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章