Android通信模块(单线程,多线程通信方式,Handler 与UI Thread的交互,Handler接合子线程的使用)
本文出自:http://blog.csdn.net/dt235201314/article/details/73823653
一丶概述
本周的学习计划是Android通信模块,内容:单线程,多线程通信方式,Handler 与UI Thread的交互,Handler接合子线程的使用。
二丶效果演示(源码链接见文末)
三丶实现功能
1.演示使用Handler常见崩溃
2.handler更新TextView的UI
3.实现图片轮播及停止
4.输出handleMessage(Message mes)的mes打印
5.自定义线程相关handler测试执行
6.Handler异步消息处理测试
handler相关方法运用
四丶正文
1.选说说多线程(工作到现在用的不太多,都是别人封装好的框架直接用)
入门文章 菜鸟教程:Java多线程编程
2.Handler
最初学习Handler是通过扣丁学堂,之前的文章:扣丁学堂——Handler
后面在开发扣丁音乐闪屏页面延时跳转功能时也有用到Handler。文章链接:扣丁音乐(一)——闪屏页SplashActivity(欢迎界面)
最近开发用到的SwipeRefreshLayout 的onRefresh()方法,也常看到handler
@Overridepublic void onRefresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { mEntities.clear(); intData(); //★3.通知recycleView改变了数据 homeAdapter.notifyDataSetChanged(); //★4.记得关闭刷新,否则刷新球一直在转 mSwipeRefreshLayout.setRefreshing(false); } }, 50);}以上基本是在整理文章前关于handler的所有运用。
好了,现在重新认识
2.Handler类的引入:
3.Handler的执行流程图:
流程图解析:
相关名词
- UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
- Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
- Message:Handler接收与处理的消息对象
- MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
- Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!
简单点说:
当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理!
4.Handler的相关方法:
- void handleMessage(Message msg):处理消息的方法,通常是用于被重写!
- sendEmptyMessage(int what):发送空消息
- sendEmptyMessageDelayed(int what,long delayMillis):指定延时多少毫秒后发送空信息
- sendMessage(Message msg):立即发送信息
- sendMessageDelayed(Message msg):指定延时多少毫秒后发送信息
- final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息
如果是参数为(int what,Object object):除了判断what属性,还需要判断Object属性是否为指定对象的消息
5.看代码
1.非UI线程线程更新UI崩溃测试:case R.id.id_btn1: new Thread() { @Override public void run() { try { Thread.sleep(1000 * 3); idTv.setText("蹦啦"); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); break;case R.id.id_btn2: new Thread() { @Override public void run() { try { Thread.sleep(1000 * 3); handler.post(new Runnable() { @Override public void run() { idTv.setText("又长帅了"); } }); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); break;
关于这里有个小插曲,涉及源码解读,观看爱哥博客
为什么我们可以在非UI线程中更新UI
2.循环播放图片及停止
Handler handler = new Handler();Thread myThread = new Thread(){ @Override public void run() { index++; index = index%3; System.out.println(index); idImg.setImageResource(images[index]); handler.postDelayed(myThread,1000); }};点击事件
case R.id.id_btn3: handler.postDelayed(myThread,1000); break;case R.id.id_btn4: handler.removeCallbacks(myThread);
handler.postDelayed(X,X)是延迟执行线程
handler.removeCallbacks(X)移除线程中所有消息和回调
3.handle传递message可携带的内容有(int 实体内等)
Handler customHander = new Handler() { @Override public void handleMessage(Message msg) { idTv.setText("msg.arg1>"+msg.arg1+ "\nmsg.arg2>" +msg.arg2 +"\nmsg.obj>"+((Person)msg.obj).toString()); }};点击事件
case R.id.id_btn5: Person dog=new Person("金三胖",1);// Message message = new Message(); Message message= customHander.obtainMessage(); message.arg1 = 1; message.arg2 = 2; message.obj = dog;// customHander.sendMessage(message); message.sendToTarget(); break;
4.消息拦截测试
Handler interceptHander = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { Toast.makeText(HandlerDemoActivity.this, "callback handleMessage", Toast.LENGTH_SHORT).show(); System.out.println("is intercept Handler>"+msg.what); // 设置true拦截消息 return true; }}){ @Override public void handleMessage(Message msg) { System.out.println("is intercept Handler"); }};点击事件
case R.id.id_btn6: interceptHander.sendEmptyMessage(1); break;5.子线程中实例化hangler崩溃测试
case R.id.id_btn7: new Thread() { @Override public void run() { try { Thread.sleep(1000*3);// idTv.setText("UI线程更新UI会出现什么异常呢?"); new Handler().post(new Runnable() { @Override public void run() { idTv.setText("又蹦啦"); } }); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); break;6.自定义一个与线程相关Handler
public class HandlerActivity extends AppCompatActivity { private MyThread myThread; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { System.out.println("UI ==:"+ Thread.currentThread()); } }; class MyThread extends Thread { public Handler handler; @Override public void run() { Looper.prepare(); handler= new Handler(){ @Override public void handleMessage(Message msg) { System.out.println("currentThread:=="+ Thread.currentThread()); } }; Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_handler); myThread = new MyThread(); myThread.start(); try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } myThread.handler.sendEmptyMessage(1); handler.sendEmptyMessage(1); }}效果打印:
06-29 17:07:30.519 9652-11848/com.example.jinboy.codertodeveloperbytcler I/System.out: currentThread:==Thread[Thread-9681,5,main]
06-29 17:07:30.659 9652-9652/com.example.jinboy.codertodeveloperbytcler I/System.out: UI ==:Thread[main,5,main]
7.Handler异步消息处理
public class HandlerThreadActivity extends AppCompatActivity implements View.OnClickListener { private Button idBtn1,idBtn2; private Handler threadhandler; private HandlerThread thread; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { System.out.println("UI thread==>" + Thread.currentThread()); // 给主线程发送消息 Message message = new Message(); message.what =1; threadhandler.sendMessageDelayed(message, 1000); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_handler_thread); idBtn1 = (Button) findViewById(R.id.id_btn1); idBtn2 = (Button) findViewById(R.id.id_btn2); idBtn1.setOnClickListener(this); idBtn2.setOnClickListener(this); thread = new HandlerThread("Handler Thread"); thread.start(); threadhandler = new Handler(thread.getLooper()) { @Override public void handleMessage(Message msg) { // 处理耗时操作 System.out.println("current thread==>" + Thread.currentThread()); // 给主线程发送消息 Message message = new Message(); message.what =1; handler.sendMessageDelayed(message, 1000); } };// threadhandler.sendEmptyMessage(1); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.id_btn1: handler.sendEmptyMessage(1); break; case R.id.id_btn2: handler.removeMessages(1); threadhandler.removeMessages(1); break; } }}打印输出
五丶参考链接和拓展学习
参考内容:
小猪博客:http://my.csdn.net/zpj779878443
慕课网课程-Android面试常客Handler详解
Android异步消息处理机制完全解析-Handler详解
拓展学习:
40个Java多线程问题总结
android进行异步更新UI的四种方式
Handler源码解析
HandlerThread的使用以及原理
Android HandlerThread 完全解析
Android异步消息处理机制完全解析,带你从源码的角度彻底理解
六丶日常开发案例
1.Android避免在主线程进行网络请求和UI操作
方法一:线程请求网络+Handler更新UI
//handler 处理返回的请求结果handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Bundle data = msg.getData(); String val = data.getString("value"); tv_name.setText(tvName); tv_originalArticleNumber.setText(tvOriginalArticleNumber); tv_visitNumber.setText(tvVisitNumber); tv_mark.setText(tvMark); tv_rank.setText(tvRank); Log.i("mylog", "请求结果-->" + val); }};//新线程进行网络请求Runnable runnable = new Runnable() { @Override public void run() { BlogAuthor blogAuthor = JsoupUtil.getBlogAutoMessage(); tvName = blogAuthor.getAuthorName() + "\n" + blogAuthor.getCode() + "\n" + blogAuthor.getMyHelloWorld(); tvOriginalArticleNumber = blogAuthor.getOriginalArticleNumber(); tvVisitNumber = blogAuthor.getVisitNumber(); tvMark = blogAuthor.getMark(); tvRank = blogAuthor.getRank(); Message msg = new Message(); Bundle data = new Bundle(); data.putString("value", "请求结果"); msg.setData(data); handler.sendMessage(msg); }};new Thread(runnable).start(); //启动子线程方法二:强制在UI线程更新UI请求网络
setContentView(R.layout.activity_main);if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);}
源码下载欢迎Star(updating):https://github.com/JinBoy23520/CoderToDeveloperByTCLer
更多相关文章
- Android开场屏 (Splash Screen)
- android sqlite遇到的一个吐血的问题
- Android源码探究:Android(安卓)Java层消息机制完全解析
- Android线程间的通信
- 怒刷Android面试100题,再也不担心不能吊打面试官了
- Android消息推送机制
- Android面试题(基础部分1)
- android中asynctask和thread的区别?
- Android通讯录管理(获取联系人、通话记录、短信消息)(三)