Android之微信图片加载
来源:互联网 发布:mac dmg 安装 编辑:程序博客网 时间:2024/05/16 18:37
MainActivity
import java.io.File;import java.io.FilenameFilter;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Set;import com.example.imageloader.bean.ImageAdapter;import com.example.imageloader.utils.ImageLoader;import com.example.imageloader.utils.ImageLoader.Type;import com.example.imageloader.utils.ImagePopupWindow;import com.example.imageloader.utils.ImagePopupWindow.OnSelectedListener;import android.app.Activity;import android.app.ProgressDialog;import android.content.ContentResolver;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.provider.MediaStore;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageButton;import android.widget.ImageView;import android.widget.PopupWindow.OnDismissListener;import android.widget.ProgressBar;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity { private GridView mGridView; private List<String> mLists; private ImageAdapter mImgAdapter; private RelativeLayout mBottomLy; private TextView mDirName; private TextView mDirCount; private File mCurrentDir; private int mMaxcount; private ProgressDialog mPd; private List<FolderBean> mFolderBeans = new ArrayList<FolderBean>(); private ImagePopupWindow mPopupWindow; private Handler handler=new Handler(){ public void handleMessage(android.os.Message msg) { if(msg.what== 0x110){ mPd.dismiss(); data2View();//绑定数据到view中; initPopupWindow(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initDatas(); initEvent(); } protected void initPopupWindow() { mPopupWindow=new ImagePopupWindow(this, mFolderBeans); mPopupWindow.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { ligthOn(); } }); //接口回调 mPopupWindow.setPopSelected(new OnSelectedListener() { @Override public void onSelected(FolderBean folderBean) { // TODO Auto-generated method stub mCurrentDir=new File(folderBean.getDir()); mLists=Arrays.asList( mCurrentDir.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { if(filename.endsWith(".jpg")||filename.endsWith(".jpeg")||filename.endsWith(".png") ){ return true; } return false; } })); mImgAdapter=new ImageAdapter(MainActivity.this, mLists, mCurrentDir.getAbsolutePath()); mGridView.setAdapter(mImgAdapter); mDirCount.setText(mLists.size()+""); mDirName.setText(folderBean.getName()); mPopupWindow.dismiss(); } }); }/** * 内容区域变亮 */ protected void ligthOn() { WindowManager.LayoutParams lp=getWindow().getAttributes(); lp.alpha=1.0f; getWindow().setAttributes(lp); } protected void data2View() { if(mCurrentDir==null){ Toast.makeText(this, "未扫描到任何图片", Toast.LENGTH_SHORT).show(); return; } mLists=Arrays.asList(mCurrentDir.list()); mImgAdapter=new ImageAdapter(this, mLists, mCurrentDir.getAbsolutePath()); mGridView.setAdapter(mImgAdapter); mDirCount.setText(mMaxcount+""); mDirName.setText(mCurrentDir.getName()); } private void initView() { mGridView = (GridView) findViewById(R.id.gridView); mBottomLy = (RelativeLayout) findViewById(R.id.rl_bottom); mDirName = (TextView) findViewById(R.id.id_dir_name); mDirCount = (TextView) findViewById(R.id.id_dir_count); } // ContentProvite扫描手机中所有图片; private void initDatas() { if (!(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED))) { Toast.makeText(this, "SD卡不可用", Toast.LENGTH_SHORT).show(); return; } mPd = ProgressDialog.show(this, null, "正在加载..."); new Thread() { public void run() { Uri mImgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;//获取媒体库图片库uri ContentResolver cr = MainActivity.this.getContentResolver(); //------------------这里的 + "= ? or " +要注意,格式要对 Cursor cursor=cr.query(mImgUri, null, MediaStore.Images.Media.MIME_TYPE + "= ? or " + MediaStore.Images.Media.MIME_TYPE + "= ? ",new String[] { "image/jpeg", "image/png" }, MediaStore.Images.Media.DATE_MODIFIED); Set<String> mDirPaths=new HashSet<String>();//储存遍历过的防止重复遍历 while(cursor.moveToNext()){ String path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));//获取每张图片的路径 File parentFile=new File(path).getParentFile();//获取图片的父文件夹 if(parentFile==null){ continue;//结束本次循环,进行下一次循环 } String dirPath=parentFile.getAbsolutePath();//获取此文件夹路径; FolderBean folderBean=null; //如果包含某个元素 if(mDirPaths.contains(dirPath)){ continue;//如果包含,结束循环 }else{ mDirPaths.add(dirPath); folderBean=new FolderBean(); folderBean.setDir(dirPath); folderBean.setFirstImagePath(path); } if(parentFile.list()==null){ continue; } //获取文件夹中图片数目,有删选 int picSize=parentFile.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { if(filename.endsWith(".jpg")||filename.endsWith(".jpeg")||filename.endsWith(".png") ){ return true; } return false; } }).length; folderBean.setCount(picSize); mFolderBeans.add(folderBean); //当前文件夹的名称数量。应该扫描一次加一张 if(picSize>mMaxcount){ mMaxcount=picSize; mCurrentDir=parentFile; } } cursor.close(); //通知handler扫描图片完成 handler.sendEmptyMessage(0x110); }; }.start(); } private void initEvent() { mBottomLy.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //mPopupWindow.setAnimationStyle(animationStyle); mPopupWindow.showAsDropDown(mBottomLy, 0, 0); lightOff(); } }); } protected void lightOff() { WindowManager.LayoutParams lp=getWindow().getAttributes(); lp.alpha=0.3f; getWindow().setAttributes(lp); }}
ImagePopupWindow
import java.util.List;import com.example.imageloader.FolderBean;import com.example.imageloader.R;import com.example.imageloader.utils.ImageLoader.Type;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.View.OnTouchListener;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.PopupWindow;import android.widget.TextView;public class ImagePopupWindow extends PopupWindow { private int mWidth; private int mHeight; private View mConvertView; private ListView mListView; private List<FolderBean> mLists; //接口回调 private OnSelectedListener mOnSelectedListener; public interface OnSelectedListener{ void onSelected(FolderBean folderBean); } public void setPopSelected(OnSelectedListener mOnSelectedListener){ this.mOnSelectedListener=mOnSelectedListener; } public ImagePopupWindow(Context context,List<FolderBean> mLists) { callWidthAndHeight(context); mConvertView=LayoutInflater.from(context).inflate(R.layout.popup, null); this.mLists=mLists; setContentView(mConvertView); setWidth(mWidth); setHeight(mHeight); setFocusable(true); setTouchable(true); setOutsideTouchable(true); setBackgroundDrawable(new BitmapDrawable()); setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_OUTSIDE){ dismiss(); return true; } return false; } }); initView(context); initEvent(); }private void initView(Context context) { mListView=(ListView) mConvertView.findViewById(R.id.lv) ; mListView.setAdapter(new ListDieAdapter(context, mLists)); }private void initEvent() { mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { mOnSelectedListener.onSelected(mLists.get(position));//接口回调 } }); }/** * 计算popupWindow的宽度和高度 * @param context */ private void callWidthAndHeight(Context context) { WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm=new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(dm); mWidth=dm.widthPixels; mHeight=(int) (dm.heightPixels*0.7); }public class ListDieAdapter extends ArrayAdapter<FolderBean>{ private LayoutInflater mInflater; //private List<FolderBean> mDatas; public ListDieAdapter(Context context, List<FolderBean> mLists) { super(context, 0, mLists); mInflater=LayoutInflater.from(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder holder; if(convertView==null){ holder=new ViewHolder(); convertView=mInflater.inflate(R.layout.popup_item, parent, false); holder.mImg=(ImageView) convertView.findViewById(R.id.pop_item_iv); holder.mDirName=(TextView) convertView.findViewById(R.id.pop_item_name); holder.mDirCount=(TextView) convertView.findViewById(R.id.pop_item_count); convertView.setTag(holder); }else{ holder=(ViewHolder) convertView.getTag(); } FolderBean fb=getItem(position); holder.mImg.setImageResource(R.drawable.ic_launcher); ImageLoader.getInstance(3,Type.LIFO).loadImage(fb.getFirstImagePath(), holder.mImg); holder.mDirCount.setText(fb.getCount()+""); holder.mDirName.setText(fb.getName()); return convertView; } private class ViewHolder{ ImageView mImg; TextView mDirName; TextView mDirCount; }}}
ImageAdapter
import java.util.HashSet;import java.util.List;import java.util.Set;import android.content.Context;import android.graphics.Color;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.widget.BaseAdapter;import android.widget.ImageButton;import android.widget.ImageView;import com.example.imageloader.R;import com.example.imageloader.utils.ImageLoader;import com.example.imageloader.utils.ImageLoader.Type;public class ImageAdapter extends BaseAdapter{ private static Set<String> mSelectedImg=new HashSet<String>(); private String mDirPath; private List<String> mImgPaths; private LayoutInflater mInflater; public ImageAdapter(Context context,List<String> mImgPaths,String mDirPath){ this.mDirPath=mDirPath; this.mImgPaths=mImgPaths; mInflater=LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return mImgPaths.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mImgPaths.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHolder holder; if(convertView==null){ holder=new ViewHolder(); convertView=mInflater.inflate(R.layout.item_gridview, parent,false); holder.mImg=(ImageView) convertView.findViewById(R.id.iv); holder.mSelect=(ImageButton) convertView.findViewById(R.id.ib); convertView.setTag(holder); }else{ holder=(ViewHolder) convertView.getTag(); } //重置状态 holder.mImg.setImageResource(R.drawable.ic_launcher); holder.mSelect.setImageResource(R.drawable.a0a); holder.mImg.setColorFilter(null); ImageLoader.getInstance(3, Type.LIFO).loadImage(mDirPath+ "/" +mImgPaths.get(position), holder.mImg); final String filePath=mDirPath+ "/" +mImgPaths.get(position); holder.mImg.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(mSelectedImg.contains(filePath)){ mSelectedImg.remove(filePath); holder.mImg.setColorFilter(null); holder.mSelect.setImageResource(R.drawable.a0a); }else{ mSelectedImg.add(filePath); holder.mImg.setColorFilter(Color.parseColor("#77000000")); holder.mSelect.setImageResource(R.drawable.a0_); } //notifyDataSetChanged(); } }); if(mSelectedImg.contains(filePath)){ holder.mImg.setColorFilter(Color.parseColor("#77000000")); holder.mSelect.setImageResource(R.drawable.a0_); } return convertView; } class ViewHolder{ ImageView mImg; ImageButton mSelect; } }
FolderBean
public class FolderBean { //当前文件夹路径 private String dir; private String firstImagePath; private String name; private int count; public FolderBean() { } public String getDir() { return dir; } public void setDir(String dir) { this.dir = dir; //获取路径最后一个“/” 的索引 int lastIndexOf=this.dir.lastIndexOf("/"); this.name=this.dir.substring(lastIndexOf+1); } public String getFirstImagePath() { return firstImagePath; } public void setFirstImagePath(String firstImagePath) { this.firstImagePath = firstImagePath; } public String getName() { return name; }// public void setName(String name) {// this.name = name;// } public int getCount() { return count; } public void setCount(int count) { this.count = count; }}
ImageLoader
import java.lang.reflect.Field;import java.util.LinkedList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v4.util.LruCache;import android.util.DisplayMetrics;import android.view.ViewGroup.LayoutParams;import android.widget.ImageView;public class ImageLoader {/** * 图片加载类 */ private static ImageLoader mInstance;//单例模式 private LruCache<String, Bitmap> mLruCache;//缓存 private ExecutorService mThreadPool;//线程池 private static final int THREAD_COUNT=1;//默认线程数 private Thread mPoolThread;//后台轮询线程 private Handler mPoolThreadHandler;//给线程发送消息的handler private Handler mUIHandler;//更新图片UI的handler private Type mType=Type.LIFO;//默认加载方式,队列调度方式 private LinkedList<Runnable> mTaskQueue;//任务队列 private Semaphore sePoolTH=new Semaphore(0);//信号量,解决并发问题 private Semaphore sePoolT;//利用信号量控制任务队列 //加载策略方式 public enum Type{ FIFO,LIFO } //初始化,可以让用户指定线程数,加载方式 private ImageLoader(int threadCont,Type type) { init(threadCont,type); } private void init(int threadCont, Type type) { //后台轮询线程 mPoolThread=new Thread(){ @Override public void run() { Looper.prepare();//启动 mPoolThreadHandler=new Handler(){ @Override public void handleMessage(Message msg) { //当接收到消息,从线程池取出任务 mThreadPool.execute(getTask()); try { sePoolT.acquire();//接收信号,开始执行。没有信号就阻塞,从而控制队列 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; sePoolTH.release();//释放一个信号量,说明已经执行好了,可以执行sePoolTH.acquire()了 Looper.loop();//在后台不断的进行轮询 } }; mPoolThread.start(); int maxMemory=(int) Runtime.getRuntime().maxMemory();//获取最大可用内存 int cacheMemory=maxMemory/8; //取8分之1 mLruCache=new LruCache<String, Bitmap>(cacheMemory){ @Override//测量每个biamap的值 protected int sizeOf(String key, Bitmap value) { // TODO Auto-generated method stub return value.getRowBytes()*value.getHeight(); } }; //初始化线程池 mThreadPool=Executors.newFixedThreadPool(threadCont); mTaskQueue=new LinkedList<Runnable>(); mType=type; sePoolT=new Semaphore(threadCont);//只能同时并发threadCont个,多的阻塞 } //从任务队列取出一个方法 private Runnable getTask() { if(mType==Type.FIFO){ return mTaskQueue.removeFirst(); }else if(mType==Type.LIFO){ return mTaskQueue.removeLast(); } return null; } //单例 public static ImageLoader getInstance(int threadCont, Type type){ if(mInstance==null){ synchronized (ImageLoader.class) { if(mInstance==null){ mInstance=new ImageLoader(THREAD_COUNT,Type.LIFO);//默认的参数 } } } return mInstance; } //根据path为imageView设置图片 public void loadImage(final String path,final ImageView imageView){ imageView.setTag(path);// if(mUIHandler==null){ mUIHandler=new Handler(){ public void handleMessage(Message msg) { //获取得到的图片,设置到imageview ImgBeanHolder holder=(ImgBeanHolder) msg.obj; Bitmap bitmap=holder.bitmap; ImageView imageView=holder.imageView; String path=holder.path; if(imageView.getTag().toString().equals(path)){ imageView.setImageBitmap(bitmap); } }; }; } //根据path在缓存中获取bitmap Bitmap bm=getBitmapFromLruCache(path); if(bm!=null){ Message message=Message.obtain(); ImgBeanHolder holder=new ImgBeanHolder();//这样下面这三个绝对是对应的。 holder.bitmap=bm; holder.path=path; holder.imageView=imageView; message.obj=holder; mUIHandler.sendMessage(message); }else{ addTasks(new Runnable() { @Override public void run() { //加载图片 //1,获取图片需要显示的大小 ImageSize imageSize=getImageViewSize(imageView); //2,压缩图片 Bitmap bm=decodeSampledBitmap(path,imageSize.width,imageSize.height); //3,把图片加入到缓存 addBitampLruCache(path,bm); Message message=Message.obtain(); ImgBeanHolder holder=new ImgBeanHolder();//这样下面这三个绝对是对应的。 holder.bitmap=bm; holder.path=path; holder.imageView=imageView; message.obj=holder; mUIHandler.sendMessage(message); sePoolT.release();//释放信号量 } }); } } protected void addBitampLruCache(String path, Bitmap bm) { if(getBitmapFromLruCache(path)==null){ if(bm!=null){ mLruCache.put(path, bm); } } } //根据图片需要显示的宽和高对图片进行压缩 protected Bitmap decodeSampledBitmap(String path, int width, int height) { BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeFile(path, options); options.inSampleSize=caculateInSampleSize(options,width,height); //使用获取到insampleSize再次解析图片; options.inJustDecodeBounds=false; Bitmap bitmap=BitmapFactory.decodeFile(path, options); return bitmap; } //计算压缩比 private int caculateInSampleSize(Options options, int reqwidth, int reqheight) { int width=options.outWidth; //图片的实际大小,要进行压缩的 int height=options.outHeight; int sampleSize=1; //如何图片的大小大于需求的大小,则进行压缩 if(width>reqwidth||height>reqheight){ int widthbili=Math.round(width*1.0f/reqwidth); int heightbili=Math.round(height*1.0f/reqheight); sampleSize=Math.max(widthbili, heightbili); } return sampleSize; } //根据imageview获取适当的压缩的宽和高 protected ImageSize getImageViewSize(ImageView imageView) { ImageSize imageSize=new ImageSize(); DisplayMetrics dm= imageView.getContext().getResources().getDisplayMetrics();//获取屏幕 LayoutParams lp=imageView.getLayoutParams(); int width= imageView.getWidth();//获取实际宽度 if(width<=0){ width=lp.width;//获取imageview在layout声明的宽度 } if(width<=0){ //width=imageView.getMaxWidth();//检查最大值 width= getImageValue(imageView, "mMaxWidth"); } if(width<=0){ width=dm.widthPixels; } int height= imageView.getHeight();//获取实际宽度 if(height<=0){ height=lp.height;//获取imageview在layout声明的宽度 } if(height<=0){ // height=imageView.getMaxHeight();//检查最大值 height= getImageValue(imageView, "mMaxHeight"); } if(height<=0){ height=dm.heightPixels; } imageSize.width=width; imageSize.height=height; return imageSize; } //通过反射获取imageView的某属性值 private static int getImageValue(Object object,String name){ int value=0; try { Field field=ImageView.class.getDeclaredField(name); field.setAccessible(true); try { int fieldValue=field.getInt(object); if(fieldValue>0 && fieldValue<Integer.MAX_VALUE){ value=fieldValue; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } return value; } private synchronized void addTasks(Runnable runnable) { mTaskQueue.add(runnable); try {//防止用到mPoolThreadHandler的时候还没初始化,如何执行到此的时候,还为空,会请求一个。这样就不回空指针了 if(mPoolThreadHandler==null) sePoolTH.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } mPoolThreadHandler.sendEmptyMessage(0x110); } private Bitmap getBitmapFromLruCache(String key) { return mLruCache.get(key); } //这个类防止加载的图片错乱,用一个对象统一。 private class ImgBeanHolder{ Bitmap bitmap; ImageView imageView; String path; } private class ImageSize{ int width; int height; }}
0 0
- Android之微信图片加载
- Android 微信分享之图片加载失败
- Android笔记之(图片高斯+Glide实现微信图片加载策略+仿微信进度条)
- android之微信分享图片
- 加载微信防盗图片
- android 之加载图片
- android之图片异步加载
- android图片加载之OOM
- Android之Glide加载图片
- Android 分享功能之 微信 图片分享
- android 微信图片选择器
- android微信图片选择器
- Android 微信分享图片!!!
- Android有效加载图片 之 使用AsyncTask异步加载图片
- Android图片压缩之鲁班Luban图片压缩(最接近微信的一种压缩)
- Android之handle异步加载图片
- Android编程之图片加载类
- Android之加载图片时自定义进度条
- 关于java编程思想的学习之方法重载
- ISE自带仿真器报错:ERROR:Simulator:861 – Failed to link the design 解决办法
- libevent使用event事件触发服务端实例
- HDU最大的位或
- SVD矩阵奇异值分解
- Android之微信图片加载
- 在 iOS 7 中获取唯一标识符(UDID/UUID)
- MongoDB数据库的基本操作
- UltimateRecyclerView
- 利用javaScript实现时间实时更新
- Android,随手保存小知识,小窍门,减少记忆负担
- VideoView播放SD卡上指定视频文件
- HDU-3047-Zjnu Stadium
- 如何使用advertisingIdentifier(IOS7不能获得MAC地址)