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
- SD浏览器并选择SD卡上的图片
- 读取sd卡上的图片
- 获取SD卡上所有的图片
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android中从SD卡中/拍照选择图片并进行剪裁的方法
- Android:从SD卡/拍照选择图片并进行剪裁的方法
- ImageView中显示SD卡上的图片或ImageView图片保存在SD卡上
- Android 关于SD卡操作 之 SD卡文件浏览器和存取SD卡上的图像
- 获取sd卡中的图片URL并显示,同时使用ImageView把选择的图片展现出来
- android-加载sd卡的图片并显示
- Android 读取sd卡图片并显示
- 在ImageView中显示SD卡上的图片
- ImageView中显示SD卡上的图片
- CentOS 7 SSH配置免密码登录
- linux awk命令详解---sql语句对等awk语句
- android的SDK更新的三种解决办法
- cocos2dx吸蓝效果实现opengl绘制
- SmartUpload实现下载的简单代码
- SD浏览器并选择SD卡上的图片
- android中引入第三方jar包方法( java.lang.NoClassDefFoundError: com.sina.weibo.sdk.auth.AuthInfo)解决办法
- 新版ADT出现appcompat_v7的问题
- swift NSNumber 转 Sting 遇到的问题
- Ubuntu 14.04一步一步安装Openstack Kilo版本-6(rabbitmq)
- mysql索引的类型和优缺点
- x210v3开发板u-boot-2012.10移植之二---如何学习uboot,掌握uboot结构
- Bean property 'manualPaperService' is not writable or has an invalid setter method. Did you mean 'ma
- c语言中内存布局问题