Andorid Handler原理及使用
来源:互联网 发布:怎么剔除异常数据 编辑:程序博客网 时间:2024/05/22 13:47
- 客户端发送http请求至服务器,如果请求成功,响应码为200,服务器会通过流向客户端返回请求的数据
- 主线程阻塞,应用会停止刷新界面,停止响应用户任何操作,用户体验非常差
- 耗时操作不要写在主线程
ANR异常
- Application not responding
消息队列
- 只有主线程可以刷新ui
- 主线程创建时,同时也会创建MessageQueue(消息队列)和Looper(消息轮询器)对象
- 如果需要使用消息队列机制,程序员需要自行创建Handler(消息处理器)
- 轮询器不断检测消息队列中是否有消息,如果有,就会把消息取出,交给Handler对象
- Handler对象拿到消息之后,就会在主线程执行handleMessage()
- 也就是说子线程,只要往消息队列中发送消息,主线程立刻执行handleMessage()
- 主线程不能被阻塞
- 在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差
- 主线程阻塞时间过长,系统会抛出ANR异常
- ANR:Application Not Response;应用无响应
- 任何耗时操作都不可以写在主线程
- 因为网络交互属于耗时操作,如果网速很慢,代码会阻塞,所以网络交互的代码不能运行在主线程
只有主线程能刷新ui
- 刷新ui的代码只能运行在主线程,运行在子线程是没有任何效果的
- 如果需要在子线程中刷新ui,使用消息队列机制
- 主线程也叫ui线程
消息队列
- 主线程创建时,系统会同时创建消息队列对象(MessageQueue)和消息轮询器对象(Looper)
- 轮询器的作用,就是不停的检测消息队列中是否有消息(Message)
- Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息
- handleMessage方法运行在主线程
主线程创建时,消息队列和轮询器对象就会被创建,但是消息处理器对象,需要使用时,自行创建
//消息队列Handler handler = new Handler(){ //主线程中有一个消息轮询器looper,不断检测消息队列中是否有新消息,如果发现有新消息,自动调用此方法,注意此方法是在主线程中运行的 public void handleMessage(android.os.Message msg) { }};
在子线程中使用Handler对象往消息队列里发消息
//创建消息对象Message msg = new Message();//消息的obj属性可以赋值任何对象,通过这个属性可以携带数据msg.obj = bm;//what属性相当于一个标签,用于区分出不同的消息,从而运行不能的代码msg.what = 1;//发送消息handler.sendMessage(msg);
通过switch语句区分不同的消息
public void handleMessage(android.os.Message msg) { switch (msg.what) { //如果是1,说明属于请求成功的消息 case 1: ImageView iv = (ImageView) findViewById(R.id.iv); Bitmap bm = (Bitmap) msg.obj; iv.setImageBitmap(bm); break; case 2: Toast.makeText(MainActivity.this, "请求失败", 0).show(); break; } }
public class MainActivity extends Activity { Handler handler = new Handler(){ //只要消息队列有消息,此方法就会在主线程执行 public void handleMessage(android.os.Message msg) { //在这里刷新ui switch (msg.what) { case 1: ImageView iv = (ImageView) findViewById(R.id.iv); iv.setImageBitmap((Bitmap)msg.obj); break; case 2: Toast.makeText(MainActivity.this, "请求失败o(╯□╰)o", 0).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ final String path = "http://169.254.244.136:8080/dd.jpg"; final File file = new File(getCacheDir(), getNameFromPath(path)); if(file.exists()){ System.out.println("从缓存获取"); Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath()); Message msg = new Message(); msg.obj = bm; msg.what = 1; handler.sendMessage(msg);// ImageView iv = (ImageView) findViewById(R.id.iv);// iv.setImageBitmap((Bitmap)msg.obj); } else{ Thread t = new Thread(){ @Override public void run() { System.out.println("从网络获取"); //发送http请求 try { //1.使用网址构造一个URL对象 URL url = new URL(path); //2.获取连接对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //3.设置一些属性 //设置请求方式,注意大写 conn.setRequestMethod("GET"); //设置请求超时 conn.setConnectTimeout(8000); //设置读取超时 conn.setReadTimeout(8000); //4.发送请求,建立连接// conn.connect(); //5.判断请求是否成功 if(conn.getResponseCode() == 200){ //获取服务器返回的流,流里就是客户端请求的数据 InputStream is = conn.getInputStream(); //我们自己读取流里的数据,读取1k,就把1k写到本地文件缓存起来 byte[] b = new byte[1024]; int len; FileOutputStream fos = new FileOutputStream(file); while((len = is.read(b)) != -1){ fos.write(b, 0, len); } fos.close(); // 因为缓存时已经把流里数据读取完了,此时流里没有任何数据 // Bitmap bm = BitmapFactory.decodeStream(is); Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath()); //当子线程需要刷新ui时,只需发送一条消息至消息队列 Message msg = new Message(); //消息对象本身是可以携带数据的 msg.obj = bm; //使用what标注消息是什么类型的 msg.what = 1; handler.sendMessage(msg); } else{ //如果消息池有消息,取出消息池第一条消息,返回,如果没有,就new一个消息返回 // Message msg = handler.obtainMessage(); // msg.what = 2; // handler.sendMessage(msg); handler.sendEmptyMessage(2); } } catch (Exception e) { e.printStackTrace(); } } }; t.start(); } } public String getNameFromPath(String path){ int index = path.lastIndexOf("/"); return path.substring(index + 1); }}
参考:Android Handler
阅读全文
0 0
- Andorid Handler原理及使用
- Andorid:Handler多种使用方式
- Handler原理及AsynTask的使用
- Handler的使用原理及方法
- Handler及原理
- Handler及原理
- Android中handler的使用及原理---学习笔记
- Android--Handler使用应运及消息机制处理原理分析
- android中的消息机制--浅谈Handler的原理及使用
- Android中handler的使用及原理---学习笔记
- handler的使用原理
- Andorid-Tint使用与原理解析
- Handler机制及原理探究
- Handler的使用与原理
- Handler 原理分析和使用
- andorid handler 消息传递机制
- Android Handler消息机制原理及总结
- Handler原理讲解及源码分析
- 初学数据结构---简单选择排序
- Andorid 代码打包--aar
- Tree Cutting(树的重心)
- spring boot配置duboo注意事项
- u盘装系统放iso文件还是gho文件?
- Andorid Handler原理及使用
- android 公共类
- java基础知识一
- JZOJ 3764. 【NOIP模拟 8.12】幸运数(lucky)
- [Unity&]PlayerPrefs.GetString的使用案例
- 最近学习易语言核心支持库的一些记录
- spark-shell读取外部数据源
- 15-JavaScript设计模式——命令模式
- 创建灰度图像直方图(c)