Android中的线程间通信(三)
来源:互联网 发布:淘宝双十一一元秒杀 编辑:程序博客网 时间:2024/06/12 01:29
Android多线程之间的消息传递是通过Handler来实现的。不同的线程之间又分为两类:即Main Thread(主线程)和Worker Thread(”苦力“线程) 。
Main Thread又称为UI Thread,意思是主线程负责Android App的界面管理与显示和与用户之间的交互,是最重要的也是最核心的Thread,所以我们要对它细心呵护,如果处理不当使UI Thread阻塞,跳出了不友善的窗口,这样是非常影响用户体验的,也是无法容忍的。
而在Andrioid多线程开发中有两点是我们必须要注意的:
1.原则上Worker线程不允许修改UI线程(即主线程)的内容或控件的,但是某些特殊的控件允许被修改,如ProgressBar等。
2.在一个应用程序中,主线程通常用于接收用户的输入,以及将运算的结果反馈给用户,所以说对于一些可能会产生阻塞的操作,如连接远程服务器下载数据信息、复杂的 数据计算等必须放置在Worker Thread中。
Main Thread还是比较好理解的,那么这个Worker Thread又该如何理解呢?相信大家也看到了我上面对它的翻译,即“苦力”线程。我们可以把一个Android App比作一个公司的Project,Thread比作一个单独的Worker,Main Thread就是一个Leader。和用户接洽这种抛头露面的事(UI)和与上级的沟通由Leader来做,苦差事都是由Worker来做,比如跑腿,搬东西,订外卖,取快递,同时不能反对Leader的意思,然后Worker把工作的结果汇报给Leader,Leader进行汇总处理。这样来类比着是不是更好理解呢。
接下来介绍一下我们今天的主角Handler,handle的字面意思是处理、解决,加上er后缀意思大概就是处理事务的东西。
作为一个Android开发菜鸟,时常听到前辈大牛们对Handler是赞不绝口,赞赏Handle设计的精妙,简洁,强大。所以我们有必要了解一下Handler工作机理,和它一起搭配干活的还有和Looper(循环器)以及MessageQueue(消息队列)。俗话说的好,没图你说个J8,哈哈。我已经准备了高清五码给大家呦,走你。
上图就能够很清晰明了的向我们描述Handler的工作流程。椭圆形代表着Handler,长方形代表MessageQueue,而正六边形就是Looper。Handler可以通过obtainMessage()方法创建许多个消息Message,然后把Message发送到MessageQueue中,(在这里提一句,MessageQueue是一个队列,有先进先出(FIFO)的特性,相信学过数据结构的小伙伴都不会陌生,如果对它还不熟的话赶快去恶补数据结构吧),然后按照先进先出顺序由Looper调用Handler的HandleMessage()方法处理(如果此刻没有消息传递过来那么Looper就会阻塞掉),注意:HandleMessage()方法是你自己需要重写的,具体实现的功能由你的实现代码决定。
以上就是今天的预备知识,理解了以上内容之后,让我们通过一个例子来看看Android是如何通过Handler来实现多线程之间通信的。
Demo:
1、布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" tools:context="com.example.administrator.handlerdemo.MainActivity"> <Button android:id="@+id/a" android:layout_width="80dp" android:layout_height="60dp" android:layout_marginTop="10dp" android:hint="Test looper" android:padding="6dp" android:text="Test looper" /> <TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" /> <Button android:id="@+id/b" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="图片下载"/> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher"/></LinearLayout>2、在MainActivity的代码:
package com.example.administrator.handlerdemo;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import com.bumptech.glide.DrawableTypeRequest;import com.bumptech.glide.Glide;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button aBtn; private Button bBtn; private TextView tv; private ImageView iv; private Handler handler; private Handler handler_iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); aBtn = (Button) findViewById(R.id.a); aBtn.setOnClickListener(this); tv = (TextView) findViewById(R.id.tv); bBtn = (Button) findViewById(R.id.b); bBtn.setOnClickListener(this); iv = (ImageView) findViewById(R.id.iv); handler = new MyHandler(); handler_iv = new MyHandler_iv(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.a: Thread thread = new NetWorkThread(); thread.start(); break; case R.id.b: Thread thread_iv = new MyThread(); thread_iv.start(); System.out.println("点击按钮事件"); break; } } //假装文字----从网络获取 public class MyHandler extends Handler { @Override public void handleMessage(Message msg) { //子类必须覆盖这个方法来接收消息 String string = (String) msg.obj; tv.setText(string); } } public class NetWorkThread extends Thread { @Override public void run() { //模拟访问网络,所以当线程运行时,会先休眠1秒钟,处理数据。 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //变量s模拟从网络中获取的数据。 //textview.setText(s); 这样的做法是错误的,因为在Android系统当中只有Main Thread才能操作UI。 String s = "Message from the server!!!"; Message msg = handler.obtainMessage(); //handler.sendMessage(msg); msg.obj = s; //sendMessage()方法,无论是在主线程当中发送,还是在Worker Thread当中发送都是可以的 handler.sendMessage(msg); } } //图片下载 class MyThread extends Thread { @Override public void run() { super.run(); DrawableTypeRequest<String> load = Glide.with(MainActivity.this).load("https://www.baidu.com/img/bd_logo1.png"); Message message = Message.obtain(); message.obj = load; handler_iv.sendMessage(message); } } class MyHandler_iv extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); DrawableTypeRequest<String> drawable = (DrawableTypeRequest<String>) msg.obj; drawable.into(iv); } }}结果如下:
【不知道为何 刚开始的时候图片很小(1图)的样子),之后多点几次图片下载就变(2图)的样子】
注意:
1、对我个人而言,我对Glide的使用不熟,在收到msg.obj的结果的时候,应该是into(iv);
2、handler发的什么就要接收什么类型的;
3、联网的时候不要忘记在清单文件配置权限;
- Android中的线程间通信(三)
- Android线程间通信(三):Looper
- Android中的线程通信
- android中的线程通信(二)
- Java中的多线程(三)之线程间的通信
- 深入理解Android中的线程及线程间通信
- java多线程(三)线程间通信
- 多线程(三)--线程间通信
- android中的线程(三上)
- android线程间通信
- Android线程间通信
- Android线程间通信
- android 线程间通信
- Android线程间通信
- Android线程间通信
- android线程间通信
- Android 线程间通信
- Android之Activity ContentProvider Service Broadcast,线程间通信,AIDL(三)
- 微服务实战(二):使用API Gateway
- 从程序员的角度分析微信小程序
- FFMpeg 3.2移植到android遇到的各种坑,再一次总结
- Java实现磁盘调度算法
- Spark 异常集锦
- Android中的线程间通信(三)
- 最大公约数
- UDP的简单封装
- 微服务实战(三):深入微服务架构的进程间通信
- JavaScript跨域总结与解决办法
- 手机/移动前端开发需要注意的20个要点
- dispatch_set_target_queue
- python之pandas的基本使用(2)
- poj 1033