记录Android异步加载的学习(线程池、信号量、图片压缩、Looper)
来源:互联网 发布:旅行物品 品牌 知乎 编辑:程序博客网 时间:2024/05/06 05:33
本文说是原创的,其实是看了各路大神的博客后记录下自己的理解,以便于以后开发的时候可以用得到。
首先感谢鸿洋_大神的文章Android 框架练成 教你打造高效的图片加载框架 ,要了解异步加载框架的可以去看这篇文章。
在这篇文章中学到了很多,也把以前比较模糊的地方重新整理了一下,这次主要是梳理一下知识点。
1.关于线程池(Executors)
记得刚做项目的时候,异步加载基本全是用AsyncTask,有多少就任务就有多少AsyncTask,以前不知道,现在才知道这样做的坏处,后来接触到线程池,管理线程,方便很多,资源得到很好地利用。
关于线程池的详细用法网上有很多文章写得很好,这里我推荐雨松MOMO的Android研究院之应用开发线程池的经典使用 ,感谢大神们的无私奉献。
创建线程池:
Executors.newSingleThreadExecutor();// 每次只执行一个线程任务的线程池 Executors.newFixedThreadPool(count);// 限制线程池大小为count的线程池 Executors.newCachedThreadPool(); // 一个没有限制最大线程数的线程池,对线程进行缓存复用 Executors.newScheduledThreadPool(3);// 一个可以按指定时间可周期性的执行的线程池 Executors.newFixedThreadPool(3, new MyThreadFactory());// 按指定工厂模式来执行的线程池 threadpool.execute(Runnable r);//加入一条线程 Future<String> f=threadpool.submit(Runnable r);//这种方式加入可以得到返回值
2.关于信号量(Semaphore)
信号量是在多线程环境下使用, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。我理解的和锁很类似。
参考文章,老紫竹JAVA提高教程-信号量(Semaphore)在生产者和消费者模式的使用
在java中,还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。
JDK中定义如下:
Semaphore(int permits, boolean fair)
创建具有给定的许可数和给定的公平设置的Semaphore。
3.图片压缩
压缩图片最重要的就是设置options.inJustDecodeBounds = true;在得到inSampleSize 后在设置生false(一定要记住,否则渠道的bitmap会空),
// 获得图片的宽和高,并不把图片加载到内存中BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(path, options);options.inSampleSize =size; //一个合适的大小 // 使用获得到的InSampleSize再次解析图片options.inJustDecodeBounds = false;Bitmap bitmap = BitmapFactory.decodeFile(path, options);
4.Looper
looper这玩意儿我看了好久问了很多大神也没彻底搞明白。
创建的线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
上面的代码里加了Looper,那么这个线程就可以循环处理消息了。
@Override public void onClick(View v) { switch (v.getId()) { case R.id.start_looper: sendMessage(); break; default: break; } } private void sendMessage() { if (UIhandler == null) { try { notEmpty.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } UIhandler.sendEmptyMessage(0); } private void backThread() { Thread thread = new Thread() { @Override public void run() { Looper.prepare(); UIhandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.i(TAG, "i:" + i++); } }; notEmpty.release(); Looper.loop(); //不加这句只有在第一次点击按钮的时候UIhandler会处理消息,即没有循环处理消息 } }; thread.start(); }
上面的代码是我写的一个例子,便于自己理解,效果就是点击一次按钮Log就会打印一次,如果没有执行Looper.loop()方法,那么就不会一直从消息队列取消息。
android的Activity也是一个消息轮询线程,有消息队列和消息循环。
- 记录Android异步加载的学习(线程池、信号量、图片压缩、Looper)
- Android 线程池、信号量、Looper、缓存初探
- Android Handler(子线程Handler)异步消息处理机制的妙用(活用信号量) 创建强大的图片加载类
- (Android学习)ImageView设置异步加载的网络图片
- Android开发之图片处理专题(三):利用ThreadPoolExcutor线程池实现多图片的异步加载
- Android异步线程,Looper, MessageQueue
- Android实现ListView异步加载图片+缓存+线程池管理
- Android 加载压缩的图片
- Android的图片异步加载
- android 异步图片的加载
- Android 图片的异步加载
- Android ListView&异步加载的学习(三)——AsyncTask加载图片&运用Lru算法优化图片加载
- Android ListView&异步加载的学习(二)——多线程加载图片
- Android-GridView 实例(异步加载,LruCache缓存,图片请求,图片压缩)
- Android中实现图片的异步加载学习笔记
- Android中实现图片的异步加载学习笔记
- Android项目实战-ListView异步图片加载及压缩缓存
- 1.Android内核 异步线程的实现(Looper、MessageQueue、Handler)
- C++迭代器 -- iterator使用简介
- viewTree
- webshell提权拿服务器方法总结
- 将整型数组中的各个值进行比对,删除重复的数值,并向前对齐,多行输入,多行输出处理
- Linux初学者笔记 续
- 记录Android异步加载的学习(线程池、信号量、图片压缩、Looper)
- [Android实例] 快速静默更新,低流量耗费,让APP活跃起来!
- YV12和I420的区别 yuv420和yuv420p的区别
- 描述性统计与性能结果分析-LoadRunner
- struts2拦截器配置实例
- TXT坐标点展开到ArcGIS中
- 使用phpMyAdmin时遇到的问题(win7)
- C++ Under the Hood
- 性能测试中的一些经验