android 仿微信选择相册中的图片跟图片异步加载
2014-03-20 13:52
411 查看
选择图片文件夹的代码:
选择图片的代码:
异步加载
public class PickPhotoActivity extends BaseActivity implements OnClickListener{ public static final int PICK_PHOTO = 125; private ArrayList<ImageData> selectedImageDatas = new ArrayList<ImageData>(); private String[] floderProjection = { "_id",//图片ID "_data",//图片uri "bucket_display_name"//图片所在文件夹名字 }; private ArrayList<String> mFloderList = new ArrayList<String>(); private ListView mFloderListView; private ImageButton back_btn,finish_btn; private TextView title_tv,selectedNumber_tv; private FloderAdapter adapter; private int canSelectNumber = 9; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.pick_photo_layout); canSelectNumber = 9-getIntent().getIntExtra("seletedNumber", 0); mFloderListView = (ListView)findViewById(R.id.floder_listView); finish_btn = (ImageButton)findViewById(R.id.title_finish_ImageButton); back_btn = (ImageButton)findViewById(R.id.back_imageButton); title_tv =(TextView)findViewById(R.id.activity_title_textView); title_tv.setText("选择图片"); back_btn.setOnClickListener(this); finish_btn.setOnClickListener(this); finish_btn.setVisibility(View.VISIBLE); selectedNumber_tv = (TextView)findViewById(R.id.select_textView); selectedNumber_tv.setText("您还可选择"+canSelectNumber+"张图片"); Cursor cursor = getContentResolver().query(Media.EXTERNAL_CONTENT_URI, floderProjection, null, null, null); if (cursor!=null) { cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++) { if (!mFloderList.contains(cursor.getString(2))) { mFloderList.add(cursor.getString(2)); } cursor.moveToNext(); } Log.d("PickPhotoActivity", "here is the floderlist size is===>" + mFloderList.size()); } adapter =new FloderAdapter(); mFloderListView.setAdapter(adapter); mFloderListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { Intent intent = new Intent(PickPhotoActivity.this, PickPhotoDetialActivity.class); intent.putExtra("canSelectNumber", canSelectNumber); intent.putExtra("floderName", mFloderList.get(arg2)); startActivityForResult(intent, PICK_PHOTO); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.back_imageButton: setResult(RESULT_CANCELED); finish(); break; case R.id.title_finish_ImageButton: Intent intent = new Intent(PickPhotoActivity.this,EditTravelActivity.class); Bundle bundle =new Bundle(); bundle.putSerializable("selectedList", selectedImageDatas); intent.putExtras(bundle); setResult(EditTravelActivity.ALBUMS, intent); finish(); break; default: break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_PHOTO && resultCode == RESULT_OK) { if (selectedImageDatas.size() != 0) { selectedImageDatas.clear(); } selectedImageDatas.addAll((ArrayList<ImageData>) data.getExtras().getSerializable("selectedList")); } selectedNumber_tv.setText("您选择了"+selectedImageDatas.size()+"张图片"); super.onActivityResult(requestCode, resultCode, data); } class FloderAdapter extends BaseAdapter{ @Override public int getCount() { // TODO Auto-generated method stub return mFloderList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mFloderList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = PickPhotoActivity.this.getLayoutInflater(); convertView=inflater.inflate(R.layout.pick_photo_list_item, null); ImageView floderImage = (ImageView) convertView.findViewById(R.id.floder_image); TextView floderName = (TextView)convertView.findViewById(R.id.floder_name); TextView photoNumber = (TextView)convertView .findViewById(R.id.photo_number); floderName.setText(mFloderList.get(position)); String image_path = null; int imageCount = 0; Cursor cursor = getContentResolver().query(Media.EXTERNAL_CONTENT_URI, floderProjection, "bucket_display_name = '" +mFloderList.get(position) + "'", null, null); if (cursor !=null) { imageCount =cursor.getCount(); cursor.moveToFirst(); image_path = cursor.getString(1);//图片路径 Log.d("PickPhoto", "the floder photo id is ===> " + image_path); } cursor.close(); photoNumber.setText(imageCount+" 张"); floderImage.setImageBitmap(getImageThumbnail(image_path,70,70)); return convertView; } } @SuppressLint("NewApi") private Bitmap getImageThumbnail(String imagePath, int width, int height) { Bitmap bitmap = null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 获取这个图片的宽和高,注意此处的bitmap为null bitmap = BitmapFactory.decodeFile(imagePath, options); options.inJustDecodeBounds = false; // 设为 false // 计算缩放比 int h = options.outHeight; int w = options.outWidth; int beWidth = w / width; int beHeight = h / height; int be = 1; if (beWidth < beHeight) { be = beWidth; } else { be = beHeight; } if (be <= 0) { be = 1; } options.inSampleSize = be; // 重新读入图片,读取缩放后的bitmap,注意这次要把options.inJustDecodeBounds 设为 false bitmap = BitmapFactory.decodeFile(imagePath, options); // 利用ThumbnailUtils来创建缩略图,这里要指定要缩放哪个Bitmap对象 bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); return bitmap; } }
选择图片的代码:
public class PickPhotoDetialActivity extends BaseActivity implements OnClickListener{ private ArrayList<ImageData> selectedImageDatas = new ArrayList<ImageData>(); ArrayList<String> selectedIdList = new ArrayList<String>(); private String[] floderProjection = { "_id", "_data", "bucket_display_name" }; private ArrayList<String> mPhotoList = new ArrayList<String>(); private GridView mPhotoGridView; private ImageButton back_btn,finish_btn; private TextView title_tv,selectedNumber_tv; private PhotoAdapter adapter; private BasicImageAsynLoader asynLoader; public Handler mAsynHandler=new Handler(); private int canSelectNumber = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pick_photo_detial); canSelectNumber = getIntent().getIntExtra("canSelectNumber", 0); asynLoader =new BasicImageAsynLoader(mAsynHandler, width); mPhotoGridView = (GridView) findViewById(R.id.photo_grid); finish_btn = (ImageButton)findViewById(R.id.title_finish_ImageButton); back_btn = (ImageButton)findViewById(R.id.back_imageButton); title_tv =(TextView)findViewById(R.id.activity_title_textView); title_tv.setText("选择图片"); back_btn.setOnClickListener(this); finish_btn.setOnClickListener(this); finish_btn.setVisibility(View.VISIBLE); selectedNumber_tv = (TextView)findViewById(R.id.select_textView); selectedNumber_tv.setText("您还可选择"+canSelectNumber+"张图片"); Cursor cursor = getContentResolver().query(Media.EXTERNAL_CONTENT_URI, floderProjection, "bucket_display_name = '" +getIntent().getExtras().getString("floderName") + "'", null, null); if (cursor !=null) { cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++) { mPhotoList.add(cursor.getString(1)); cursor.moveToNext(); } } cursor.close(); adapter = new PhotoAdapter(); mPhotoGridView.setAdapter(adapter); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.back_imageButton: setResult(RESULT_CANCELED); finish(); break; case R.id.title_finish_ImageButton: for (int i = 0; i < selectedIdList.size(); i++) { ImageData data = new ImageData(); data.setUrl(selectedIdList.get(i)); selectedImageDatas.add(data); } Intent intent = new Intent(PickPhotoDetialActivity.this,PickPhotoActivity.class); Bundle bundle =new Bundle(); bundle.putSerializable("selectedList", selectedImageDatas); intent.putExtras(bundle); setResult(RESULT_OK, intent); finish(); break; default: break; } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @SuppressLint({ "NewApi", "ShowToast" }) public class PhotoAdapter extends BaseAdapter { @Override public int getCount() { return mPhotoList.size(); } @Override public Object getItem(int position) { return mPhotoList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } class ViewHolder { ImageButton pickBtn; ImageView imageView; } @Override public View getView(int position, View convertView, ViewGroup parent) { final int index =position; final ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); LayoutInflater inflater = PickPhotoDetialActivity.this.getLayoutInflater(); convertView=inflater.inflate(R.layout.pick_photo_grid_item, null); holder.imageView = (ImageView)convertView.findViewById(R.id.image); holder.pickBtn = (ImageButton) convertView.findViewById(R.id.pick_btn); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } getThumb(holder.imageView,mPhotoList.get(position)); holder.pickBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!selectedIdList.contains(mPhotoList.get(index))) { if (selectedIdList.size() < canSelectNumber) { selectedIdList.add(mPhotoList.get(index)); } else { Toast.makeText(PickPhotoDetialActivity.this, "最多选择"+canSelectNumber+"张图片!", Toast.LENGTH_SHORT).show(); } } else { selectedIdList.remove(mPhotoList.get(index)); } selectedNumber_tv.setText("你已选择了"+ selectedIdList.size()+"张图片!"); notifyDataSetChanged(); } }); if (selectedIdList.contains(mPhotoList.get(index))) { holder.pickBtn.setBackgroundResource(R.drawable.pick_photo_pressed); //holder.pickBtn.setTag(1); } else { holder.pickBtn.setBackgroundResource(R.drawable.pick_photo_normal); } return convertView; } } private void getThumb(final ImageView itemImage,String strPath) { itemImage.setTag(strPath); asynLoader.loadBitmap(itemImage, true, strPath); } // @SuppressLint("NewApi") }
异步加载
import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.graphics.Bitmap; import android.os.Handler; import android.util.Log; import android.widget.ImageView; /** * * @author hwang * * * */ public final class BasicImageAsynLoader { private LoaderThread thread;// 加载图片并发消息通知更新界面的线程 private HashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的url private boolean isphoto; // private ExecutorService executorService = Executors.newFixedThreadPool(5);//这个线程池最好在引用该类的地方new新的,在引用的Activity关闭时关闭该线程池。 private Handler handler;// 界面Activity的Handler对象 e private int width; public BasicImageAsynLoader(Handler handler,int width) { imageCache = new HashMap<String, SoftReference<Bitmap>>(); this.handler = handler; this.width = width; } /** * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中 * * @param imageView * 要显示图片的视图 * @param defaultBitmap * 加载需要显示的提示正在加载的默认图片对象 */ public void loadBitmap(final ImageView imageView, Boolean isPhoto,final String url,ExecutorService executorService) { // 图片所对应的url,这个值在加载图片过程中很可能会被改变 // String url = (String) imageView.getTag(); Log.d("PVthumb","the url is===>"+url); if (imageCache.containsKey(url)) {// 判断缓存中是否有 SoftReference<Bitmap> softReference = imageCache.get(url); Bitmap bitmap = softReference.get(); if (bitmap != null) {// 如果图片对象不为空,则可挂接更新视图,并返回 imageView.setImageBitmap(bitmap); return; } else {// 如果为空,需要将其从缓存中删除(其bitmap对象已被回收释放,需要重新加载) Log.e("TAG", "cache bitmap is null"); imageCache.remove(url); } } isphoto=isPhoto; //线程池加载 executorService.execute(new Runnable() { @Override public void run() { final Bitmap bitmap; if (isphoto) { Log.d("Pvthumb","the url is====>>>"+url); bitmap = CommonUtil.getImageThumbnail(url,null, width/4-1, width/4-1);// 此方法应该是从网络或sd卡中加载 Log.d("hwang","thebitmap is ==>"+bitmap); }else { bitmap =null; } // 将加载的图片放入缓存map中 imageCache.put(url, new SoftReference<Bitmap>(bitmap)); if (url == imageView.getTag()) {// 再次判断视图有没有复用 handler.post(new Runnable() {// 通过消息机制在主线程中更新UI public void run() { imageView.setImageBitmap(bitmap); } }); } } }); /*这个是单线程异步加载适合低端机型 // imageView.setImageBitmap(defaultBitmap);// 先显示一个提示正在加载的图片 if (thread == null) {// 加载线程不存在,线程还未启动,需要新建线程并启动 thread = new LoaderThread(imageView, url); thread.start(); } else {// 如果存在,就调用线程对象去加载 thread.load(imageView, url); } */ } /** * 释放缓存中所有的Bitmap对象,并将缓存清空 064 */ public void releaseBitmapCache() { if (imageCache != null) { for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) { Bitmap bitmap = entry.getValue().get(); if (bitmap != null) { bitmap.recycle();// 释放bitmap对象 } } imageCache.clear(); } } /** * 加载图片并显示的线程 */ public class LoaderThread extends Thread { LinkedHashMap<String, ImageView> mTaskMap;// 需要加载图片并显示的图片视图对象任务链 private boolean mIsWait;// 标识是线程是否处于等待状态 public LoaderThread(ImageView imageView, String url) { mTaskMap = new LinkedHashMap<String, ImageView>(); mTaskMap.put(url, imageView); } /** * 处理某个视图的更新显示 * * @param imageView */ public void load(ImageView imageView, String url) { mTaskMap.remove(imageView);// 任务链中可能有,得先删除 mTaskMap.put(url, imageView);// 将其添加到任务中 if (mIsWait) {// 如果线程此时处于等待得唤醒线程去处理任务队列中待处理的任务 synchronized (this) {// 调用对象的notify()时必须同步 this.notify(); } } } @Override public void run() { while (mTaskMap.size() > 0) {// 当队列中有数据时线程就要一直运行,一旦进入就要保证其不会跳出循环 mIsWait = false; final String url = mTaskMap.keySet().iterator().next(); final ImageView imageView = mTaskMap.remove(url); if (imageView.getTag() == url) {// 判断视图有没有复用(一旦ImageView被复用,其tag值就会修改变) final Bitmap bitmap; if (isphoto) { Log.d("Pvthumb","the url is====>>>"+url); bitmap = CommonUtil.getImageThumbnail(url,null, width/4-1, width/4-1);// 此方法应该是从网络或sd卡中加载 Log.d("hwang","thebitmap is ==>"+bitmap); }else { bitmap =null; } // 将加载的图片放入缓存map中 imageCache.put(url, new SoftReference<Bitmap>(bitmap)); if (url == imageView.getTag()) {// 再次判断视图有没有复用 handler.post(new Runnable() {// 通过消息机制在主线程中更新UI public void run() { imageView.setImageBitmap(bitmap); } }); } } if (mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态 try { mIsWait = true;// 标识线程的状态,必须在wait()方法之前 synchronized (this) { this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒 } } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
相关文章推荐
- 安卓开发第一个小程序HelloWorld
- 微信公共账号开发(未认证服务号)
- 使用微信api接口开发的框架
- PHP实现微信公众平台音乐点播
- 微信利用PHP创建自定义菜单的方法
- 【转帖】微信公众平台接口傻瓜教程(个人整理)
- Android中使用GridView实现仿微信图片上传功能(附源代码)
- PHP实现微信公众平台音乐点播
- 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- 微信公众平台开发接口PHP SDK完整版
- 如何在FireFox浏览器上访问微信公共账户提供的链接
- Android 微信分享 bug 3月体验
- 关于《core java》中打印日历小程序的总结
- 微信公众平台开发[13]-html5新颖活动-摇一摇
- 微信支付----没我想的那么难!
- 微信相关的应用
- 跟上潮流,做个微信开发者平台
- 每天一个小程序(4)——顺序栈
- 第二讲 探秘微信公众号
- 微信公众平台 token & access_token