SD浏览器并选择SD卡上的图片

来源:互联网 发布:南侨机工英雄传 知乎 编辑:程序博客网 时间:2024/05/15 23:44

      学习的过程中遇到了许多问题,像加载大量图片出现的oom、卡顿 等问题都是不可避免的,这个例子算是比较好的解决了以上问题,不过还有可以改进的地方,可以使用LruCache来缓存图片


SD浏览器:打开手机上的sd卡,并点击选择图片到数据库。
若某文件是图片:用其缩略图表示,若是文件夹就用文件夹图标表示,其他文件为了简单也用文件夹表示。
点击某一项:若是图片:会将图片的名与路径添加到数据库,如若是文件夹,会打开进入该文件夹,如是其他文件会提示。
listview的滚动监听会释放不显示的图片,与之配合的MyBaseAdapter异步加载sd卡上的图片并对其进行了缩放,解决了oom与卡慢的情况。

</pre><pre class="java" name="code">
</pre><pre class="java" name="code">public class SDFileExplorer extends Activity implements AbsListView.OnScrollListener{    ListView listView;    TextView textView;    // 记录当前的父文件夹    File currentParent;    // 记录当前路径下的所有文件的文件数组    File[] currentFiles;        MyDatabaseHelper db;    Cursor cursor;    List<Map<String, Object>> listItems;    MyBaseAdapter adapter;    Map<String, Object> listItem;       public static Map<String,Bitmap> gridviewBitmapCaches = new HashMap<String,Bitmap>();    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_sdfile_explorer);        //data=new Bundle();        // 获取列出全部文件的ListView        listView = (ListView) findViewById(R.id.list);        textView = (TextView) findViewById(R.id.path);        listView.setOnScrollListener(this);        db=new MyDatabaseHelper(this,"my.path",1);        cursor = db.getReadableDatabase().rawQuery("select * from data ",null);        // 获取系统的SD卡的目录        File root = new File("/mnt/sdcard/");        // 如果 SD卡存在        if (root.exists())        {            currentParent = root;            currentFiles = root.listFiles();            // 使用当前目录下的全部文件、文件夹来填充ListView            inflateListView(currentFiles);        }        // 为ListView的列表项的单击事件绑定监听器        listView.setOnItemClickListener(new OnItemClickListener()        {            @Override            public void onItemClick(AdapterView<?> parent, final View view,                                    final int position, long id)            {                //图片将被添加进数据库                 if(isImage(getFileType(currentFiles[position].getName()))){                    insert(db.getReadableDatabase(), currentFiles[position].getName(), currentFiles[position].getPath().toString());                    Toast.makeText(SDFileExplorer.this                            , "添加成功!",                            Toast.LENGTH_SHORT).show();                            //点击 的 动画 效果                     Animation anim= AnimationUtils.loadAnimation(SDFileExplorer.this,R.anim.delete_listitem);                            view.startAnimation(anim);                }                // 获取用户点击的文件夹下的所有文件                else{                File[] tmp = currentFiles[position].listFiles();                if (tmp == null || tmp.length == 0)                {                    Toast.makeText(SDFileExplorer.this                            , "当前路径不可访问或该路径下没有文件",                            Toast.LENGTH_SHORT).show();                }                else                {                    // 获取用户单击的列表项对应的文件夹,设为当前的父文件夹                    currentParent = currentFiles[position]; //②                    // 保存当前的父文件夹内的全部文件和文件夹                    currentFiles = tmp;                    // 再次更新ListView                    inflateListView(currentFiles);                }            }}        });        // 获取上一级目录的按钮        Button parent = (Button) findViewById(R.id.parent);        Button finish = (Button) findViewById(R.id.finish);        parent.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View source)            {                try                {                    if (!currentParent.getCanonicalPath()                            .equals("/"))                    {                        // 获取上一级目录                        currentParent = currentParent.getParentFile();                        // 列出当前目录下所有文件                        currentFiles = currentParent.listFiles();                        // 再次更新ListView                        inflateListView(currentFiles);                    }                }                catch (IOException e)                {                    e.printStackTrace();                }            }        });        finish.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View source)            {                 db.close();                SDFileExplorer.this.finish();            }        });    }    private void inflateListView(final File[] files) //①    {        // 创建一个List集合,List集合的元素是Map        listItems =new ArrayList<Map<String, Object>>();        for (int i = 0; i < files.length; i++)        {           listItem =                    new HashMap<String, Object>();            // 如果当前File是文件夹,使用folder图标;否则使用file图标            if (files[i].isDirectory())            {                listItem.put("uri", null);            }            else  if(isImage(getFileType(files[i].getName())))            {                listItem.put("uri", files[i].getPath());            }            else            {                listItem.put("uri", null);            }            listItem.put("fileName", files[i].getName());            // 添加List项            listItems.add(listItem);        }        adapter= new MyBaseAdapter(this, listItems);        listView.setAdapter(adapter);        try        {            textView.setText("当前路径为:" + currentParent.getCanonicalPath());        }        catch (IOException e)        {            e.printStackTrace();        }    }    public static String getFileType(String fileName) {        if (fileName != null) {            int typeIndex = fileName.lastIndexOf(".");            if (typeIndex != -1) {                String fileType = fileName.substring(typeIndex + 1)                        .toLowerCase();                return fileType;            }        }        return "";    }    /**     * 根据后缀名判断是否是图片文件     *     * @param type     * @return 是否是图片结果true or false     */    public static boolean isImage(String type) {        if (type != null                && (type.equals("jpg") || type.equals("gif")                || type.equals("png") || type.equals("jpeg")                || type.equals("bmp") || type.equals("wbmp")                || type.equals("ico") || type.equals("jpe"))) {            return true;        }        return false;    }    private void insert(SQLiteDatabase db,String ed1,String ed2){            db.execSQL("insert into data values(null,?,?)",new String[]{ed1,ed2});    }    public final class Holder {        public TextView text;        public ImageView image;    }    //释放图片的函数    private void recycleBitmapCaches(int fromPosition,int toPosition){        Bitmap delBitmap = null;        for(int del=fromPosition;del<toPosition;del++){            delBitmap = gridviewBitmapCaches.get(listItems.get(del).get("uri"));            if(delBitmap != null){                //如果非空则表示有缓存的bitmap,需要清理                Log.e( "release position:" , "");                //从缓存中移除该del->bitmap的映射                gridviewBitmapCaches.remove(listItems.get(del).get("uri"));                delBitmap.recycle();                delBitmap = null;            }        }    }    public void onScroll(AbsListView view, int firstVisibleItem,                         int visibleItemCount, int totalItemCount) {        // TODO Auto-generated method stub        //注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变        //visibleItemCount为当前页面总共可见的Item的项数        //totalItemCount为当前总共已经出现的Item的项数        recycleBitmapCaches(0,firstVisibleItem);        recycleBitmapCaches(firstVisibleItem+visibleItemCount, totalItemCount);    }    public void onScrollStateChanged(AbsListView view, int scrollState) {        // TODO Auto-generated method stub    }}


下面是上面listview用到的baseadapter。

与之配合的MyBaseAdapter异步加载sd卡上的图片并对其进行了缩放,解决了oom与卡慢的情况。

/** * Created by lzw on 2015/6/6. */public  class MyBaseAdapter extends BaseAdapter{    private static Context mContext = null;    private LayoutInflater mLayoutInflater = null;    private List<Map<String, Object>> mList = null;    private int width = 100;//每个Item的宽度,可以根据实际情况修改    private int height = 100;//每个Item的高度,可以根据实际情况修改    public static class MyGridViewHolder{        public ImageView imageview_thumbnail;        public TextView textview_test;    }    public MyBaseAdapter(Context context,List<Map<String, Object>> mList) {        // TODO Auto-generated constructor stub        this.mContext = context;        this.mList = mList;        mLayoutInflater = LayoutInflater.from(context);    }    public int getCount() {        // TODO Auto-generated method stub        return mList.size();    }    public Object getItem(int arg0) {        // TODO Auto-generated method stub        return null;    }    public long getItemId(int position) {        // TODO Auto-generated method stub        return 0;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        Map map = mList.get(position);        String url=(String)map.get("uri");        String name=(String)map.get("fileName");        MyGridViewHolder viewHolder = null;        if(convertView == null){            viewHolder = new MyGridViewHolder();            convertView = mLayoutInflater.inflate(R.layout.cell2, null);            viewHolder.imageview_thumbnail = (ImageView)convertView.findViewById(R.id.imagecell2);            viewHolder.textview_test = (TextView)convertView.findViewById(R.id.textcell2);            convertView.setTag(viewHolder);                    }else{            viewHolder = (MyGridViewHolder)convertView.getTag();        }        //表示不是图片,用文件夹图标表示         if(url==null){viewHolder.imageview_thumbnail.setImageResource(R.drawable.folder);}        //首先我们先通过cancelPotentialLoad方法去判断imageview是否有线程正在为它加载图片资源,        //如果有现在正在加载,那么判断加载的这个图片资源(url)是否和现在的图片资源一样,不一样则取消之前的线程(之前的下载线程作废)。        //见下面cancelPotentialLoad方法代码        else {            if (cancelPotentialLoad(url, viewHolder.imageview_thumbnail)) {                AsyncLoadImageTask task = new AsyncLoadImageTask(viewHolder.imageview_thumbnail);                LoadedDrawable loadedDrawable = new LoadedDrawable(task);                viewHolder.imageview_thumbnail.setImageDrawable(loadedDrawable);                task.execute(position);            }        }        viewHolder.textview_test.setText(name);        return convertView;    }    //也可以换成从网上下载图片    private Bitmap getBitmapFromUrl(String url){        Bitmap bitmap = null;        bitmap = SDFileExplorer.gridviewBitmapCaches.get(url);        if(bitmap != null){            System.out.println(url);            return bitmap;        }        //该方法返回一个缩放成宽width,高height的bitmap        bitmap = getBitmapThumbnail(url, width, height);        return bitmap;    }    public  Bitmap getBitmapThumbnail(String path,int width,int height){                Bitmap bm;                BitmapFactory.Options opt = new BitmapFactory.Options();                //这个isjustdecodebounds很重要                opt.inJustDecodeBounds = true;                  bm = BitmapFactory.decodeFile(path, opt);                //获取到这个图片的原始宽度和高度                int picWidth  = opt.outWidth;                int picHeight = opt.outHeight;                //获取屏的宽度和高度</div><div>                int screenWidth = 100;                int screenHeight = 100;                        //isSampleSize是表示对图片的缩放程度,比如值为2图片的宽度和高度都变为以前的1/2                opt.inSampleSize = 1;                //根据屏的大小和图片大小计算出缩放比例                if(picWidth > picHeight){                    if(picWidth> screenWidth)                        opt.inSampleSize = picWidth/screenWidth;                }                else{                    if(picHeight > screenHeight)                        opt.inSampleSize = picHeight/screenHeight;                }                //这次再真正地生成一个有像素的,经过缩放了的bitmap                opt.inJustDecodeBounds = false;                bm = BitmapFactory.decodeFile(path, opt);                return bm;    }  //加载图片的异步任务    private class AsyncLoadImageTask extends AsyncTask<Integer, Void, Bitmap> {        private String url = null;        private final WeakReference<ImageView> imageViewReference;        public AsyncLoadImageTask(ImageView imageview) {            super();            // TODO Auto-generated constructor stub            imageViewReference = new WeakReference<ImageView>(imageview);        }        @Override        protected Bitmap doInBackground(Integer... params) {            // TODO Auto-generated method stub            Bitmap bitmap = null;            Map map=mList.get(params[0]);            this.url =(String) map.get("uri");            bitmap = getBitmapFromUrl(url);            SDFileExplorer.gridviewBitmapCaches.put((String) map.get("uri"), bitmap);            return bitmap;        }        @Override        protected void onPostExecute(Bitmap resultBitmap) {            // TODO Auto-generated method stub            if(isCancelled()){                resultBitmap = null;            }            if(imageViewReference != null){                ImageView imageview = imageViewReference.get();                AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);                if (this == loadImageTask) {                    imageview.setImageBitmap(resultBitmap);                    imageview.setScaleType(ImageView.ScaleType.CENTER_INSIDE);                }            }            super.onPostExecute(resultBitmap);        }    }    private boolean cancelPotentialLoad(String url,ImageView imageview){        AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);        if (loadImageTask != null) {            String bitmapUrl = loadImageTask.url;            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {                loadImageTask.cancel(true);            } else {                // 相同的url已经在加载中.                return false;            }        }        return true;    }    //当 loadImageTask.cancel(true)被执行的时候,则AsyncLoadImageTask 就会被取消,    //当AsyncLoadImageTask 任务执行到onPostExecute的时候,如果这个任务加载到了图片,    //它也会把这个bitmap设为null了。    //getAsyncLoadImageTask代码如下:    private AsyncLoadImageTask getAsyncLoadImageTask(ImageView imageview){        if (imageview != null) {            Drawable drawable = imageview.getDrawable();            if (drawable instanceof LoadedDrawable) {                LoadedDrawable loadedDrawable = (LoadedDrawable)drawable;                return loadedDrawable.getLoadImageTask();            }        }        return null;    }    //该类功能为:记录imageview加载任务并且为imageview设置默认的图片    public static class LoadedDrawable extends BitmapDrawable {        private final WeakReference<AsyncLoadImageTask> loadImageTaskReference;        public LoadedDrawable(AsyncLoadImageTask loadImageTask) {             //R.drawable.ic_launcher即为默认的图片            super(BitmapFactory.decodeResource(mContext.getResources(),R.drawable.ic_launcher)            );            loadImageTaskReference =                    new WeakReference<AsyncLoadImageTask>(loadImageTask);        }        public AsyncLoadImageTask getLoadImageTask() {            return loadImageTaskReference.get();        }    }}


MyDatabaseHelper.java

SDFileExplorer中用到的创建数据库的代码

public class MyDatabaseHelper extends SQLiteOpenHelper{    final String CREATE_TABLE_SQL =            "create table data(id integer primary key autoincrement, name , uri)";    public MyDatabaseHelper(Context context, String name, int version)    {        super(context, name, null, version);    }    @Override    public void onCreate(SQLiteDatabase db)    {        db.execSQL(CREATE_TABLE_SQL);    }    @Override    public void onUpgrade(SQLiteDatabase db            , int oldVersion, int newVersion)    {        System.out.println("--------onUpdate Called--------"                + oldVersion + "--->" + newVersion);    }}





0 0
原创粉丝点击