一、需求分析

在使用okhttp的时候,有时会遇到需要在onresponse中将数据传送到其他线程中,或者是发送消息给UI线程,通知其更改UI的情况,并且我想返回的数据不是普通数据,而是一个类的对象。
下面说的几种方法,并不局限于在Okhttp中使用,而是线程之间传递数据(或者消息)都可以用到

二、使用的方法

  1. 使用全局变量的方法将数据从onresponse中获取下来,然后在将其返回

  2. 用Handler+Message的方法将数据传输到其他线程

  3. 用Handler+Message+Bundle的方法将一系列数据传输到其他线程

  4. 用Handler+Message+Serializable接口,返回一个类的对象

三、具体的实现

  1. 使用全局变量的方法将数据从onresponse中获取下来,然后在将其返回

    UI线程的代码:

    public class MainActivity extends AppCompatActivity {private String str = "nothing";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//调用Test方法TryTest.Test();//获取Test中的数据str = TryTest.getStr();Log.d("TryMain", "str = " + str);}
    }
    

    子线程的代码:

    public class TryTest {private static String test_str;public static void Test(){new Thread(new Runnable() {@Overridepublic void run() {setStr("Hello");Log.d("TryTest","str = " + getStr());}}).start();}public static String getStr(){return test_str;}public static void setStr(String test_str) {TryTest.test_str = test_str;}
    }
    

    在主线程中,我定义了一个String对象str用于接收来自子线程的数据,然后在子线程中通过全局变量将test_str通过setStr()方法在子线程中定义,通过getStr()的方法进行返回.
    运行结果如下:

可以看到在主线程中的str并没有被赋值,而str子子线程中是有值的,为什么会这样呢?因为我们在调用Test方法时,其中的子线程与主线程时同时进行的,所以主线程还没等到子线程的值就已经往下执行了,从运行结果的顺序也可以看出来是先执行的主线程的log,然后再执行的子线程的log。

那要怎样才能让主线程等子线程的数据返回之后再继续往下执行呢?难道调用sleep的方法让主线程等一会儿?那么要等多久才合适呢?有没有什么办法能够让子线程获取数据之后通知主线程往下执行呢?这就是接下来要将的方法:调用Handler+Message。

  1. 用Handler+Message的方法将数据传输到其他线程

    UI线程的代码:

    public class MainActivity extends AppCompatActivity {private String str = "nothing";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//接受信息@SuppressLint("HandlerLeak") Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//msg.what对应子线程中msg的标签,在子线程中进行赋值if(msg.what==1){str = TryTest.getStr();Log.d("TryMain", "Handle str = " + str);}}};Log.d("TryMain", "Main str = " + str);TryTest.Test(mHandler);}
    }
    

    子线程中的代码:

    public class TryTest {private static String test_str;public static void Test(final Handler mHandler){new Thread(new Runnable() {@Overridepublic void run() {setStr("Hello");Log.d("TryTest","Test str = " + getStr());Message msg = new Message();msg.what = 1;//发送消息mHandler.sendMessage(msg);}}).start();}public static String getStr(){return test_str;}public static void setStr(String test_str) {TryTest.test_str = test_str;}
    }
    

    相比之前的代码,我们在主线程中增加了一个Handler用于接收返回的数据并决定接下来的操作;我们在子线程中增加了Message用来传递消息。注意我们将在主线程中创建的Handler作为参数传入了方法中,这就像小时候玩的传话筒一样,要两个话筒连在同一条线上,才能听到对方说了什么。
    运行结果如下:

    可以看到这次我们在Handler中的str已经被子线程赋值了,从执行顺序上看,是执行了主线程中的方法,然后执行子线程的方法,在子线程中传递消息,最后在主线程中收到消息之后,执行Handler中的方法,这样就实现的等待收到消息之后再执行的功能。

    不过我解决需求时,在网上查阅的方法都没有用这个方法,而是用的后面两种方法:

  2. 用Handler+Message+Bundle的方法将一系列数据传输到其他线程

    UI线程的代码:

    public class MainActivity extends AppCompatActivity {private String str = "nothing";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);@SuppressLint("HandlerLeak") final Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what==1){//获取子线程传来的数据,并将其拼接起来str = msg.getData().getString("first");str += msg.getData().getString("second");str += msg.getData().getString("third");Log.d("TryMain", "Handle str = " + str);}}};Log.d("TryMain", "Main str = " + str);TryTest.Test(mHandler);}
    }
    

    子线程中的代码:

    public class TryTest {public static void Test(final Handler mHandler){new Thread(new Runnable() {@Overridepublic void run() {Bundle bundle = new Bundle();//使用键值对的方式进行传输数据bundle.putString("first","Are ");bundle.putString("second","you ");bundle.putString("third","ok?");Message msg = new Message();msg.what = 1;msg.setData(bundle);mHandler.sendMessage(msg);}}).start();}
    }
    

    由于比较简单,所以就过多的讲解了,这里就是将多个数据通过Bundle联系起来,最后只需要通过一个Bundle的实例就可以将多个数据同时传送出去。

    运行结果如下:


    当然,由于bundle只能传输如int,String这样简单的数据,所以传出去的是一个个单独的个体,接受的那边还需要一个个的获取,如果传送的是一个类的数据的话,就会导致封装性不够好,调用起来也会比较麻烦,所以就有了下面这个方法

  3. 用Handler+Message+Serializable接口,返回一个类的对象

    首先创建一个实体类,实现Serializable接口

    Serializable接口是启用其序列化的接口,简单的说就是将其状态转换为字节码,这样在传输的时候就可以不用管数据的类型了(我是这样认为的)

    public class TestClass implements Serializable {private String name;private String id;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}
    }
    

    UI线程的代码:

    public class MainActivity extends AppCompatActivity {private String str = "nothing";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);@SuppressLint("HandlerLeak") final Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what==1){TestClass testClass = (TestClass) msg.getData().getSerializable("TestClass");str = testClass.getName();Log.d("TryMain", "Handle str = " + str);}}};Log.d("TryMain", "Main str = " + str);TryTest.Test(mHandler);}
    }
    

    子线程中的代码:

    public class TryTest {public static void Test(final Handler mHandler){new Thread(new Runnable() {@Overridepublic void run() {TestClass testClass = new TestClass();testClass.setId("1001");testClass.setName("这是一个Test");Bundle bundle = new Bundle();bundle.putSerializable("TestClass", testClass);Message msg = new Message();msg.what = 1;msg.setData(bundle);mHandler.sendMessage(msg);}}).start();}
    }
    

    道理都是一样的,只是使用的方法不同

    运行结果如下:

五、后三个方法的优缺点

  1. 使用Handler+Message,以及全局变量的方法重在简单,也很实用,直接调用就可以返回需要的数据,也不用管是什么数据类型,不过只能传一个数据过去
  2. 使用Handler+Message+Bundle的方法则是可以传输多个数据,缺点是只能传输基础数据类型
  3. Handler+Message+Bundle+Serializable接口则是在上一个方法的基础上进行补充,使其可以传输其他类型的数据

注意事项:

这里的都是子线程与主线程(UI线程)之间通信以及传数据,在主线程中,系统已经为我们定义好了Looper.prepare(),所以我们不用单独定义Looper.prepare(),而如果是在子线程之间传递信息的话,则需要在接收信息的的线程中添加Looper.prepare()
代码如下:

public class TryTest {private static Handler mHandler;public static void Test(){//        接收信息的线程new Thread(new Runnable() {@SuppressLint("HandlerLeak")@Overridepublic void run() {Looper.prepare();mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what==1){Log.d("GET","Get it!");}}};Looper.loop();}}).start();
//        发送信息的线程new Thread(new Runnable() {@Overridepublic void run() {Message msg = new Message();msg.what = 1;Log.d("Send","Send it!");mHandler.sendMessage(msg);}}).start();}
}

重点是要在接受信息的线程中添加Looper.prepare(),以及Looper.loop()
运行结果如下:

其他的使用都和前面的没有区别

希望对你有帮助
能力有限,欢迎各位指出我的问题

线程之间传递信息的几种方法 Android相关推荐

  1. Android之UI线程与子线程交互设计的5种方法

    转载地址:http://www.cr173.com/html/19165_1.html 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于 ...

  2. android fragment传递参数_fragment之间传值的两种方法

    在Activity中加载Fragment的时候.有时候要使用多个Fragment切换.并传值到另外一个Fragment.也就是说两个Fragment之间进行参数的传递.查了很多资料.找到两种方法.一种 ...

  3. 线程间通信的三种方法 (转)

    http://www.cnblogs.com/puxidun/archive/2009/12/06/1618142.html 线程间通信的三种方法 多线程通信的方法主要有以下三种:  1.全局变量 进 ...

  4. Vue组件之间传值的几种方法 (直接上代码)

    vue组件之间传值的几种方法总结 一. props(父传子) 父组件 传递 <template><div><HelloWorld :msg="msg" ...

  5. android线程间通信的几种方法_Android进程间和线程间通信方式

    进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位 ...

  6. android线程间通信的几种方法_Android线程间通信机制

    讲解Handler机制的博文很多,我也看了很多,但说实话,在我对Handler几乎不怎么了解的情况下,每一篇文章我都没太看懂,看完之后脑子里还是充满了疑问.究其原因,是因为几乎每一篇文章一上来就开始深 ...

  7. 线程间同步的几种方法--互斥锁,条件变量,信号量,读写锁

    一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码. 1 . 初始化锁 int pthread_mutex_init(pthread_mutex_t *mutex,cons ...

  8. JAVA如何在线程中加锁(四种方法)

    JAVA多线程锁 线程的生命周期 ​ 总共六种状态,可归结为五种,线程的最终是死亡,阻塞不是最终状态,只是一个临时状态.只有调用了start方法,线程才进入就绪阶段. //新生 ​ NEW, //运行 ...

  9. 如何在窗体之间通讯的几种方法 ? VB.NET方案

    在面向过程的程序中,我们可以通过窗体名来访问其他窗体中控件或者数据,但是在面向过程中却稍有不同,面向过程显示了它的优点. 假设一个Window解决方案中,有两个窗体Form1和Form2,Form1窗 ...

最新文章

  1. 单个Transformer完成信息检索,谷歌用可微搜索索引打败双编码器模型
  2. Spring MVC 的跨域解决方案
  3. 对于坐拥海量数据的金融企业来说,大数据治理意味着什么?
  4. Dokcer容器实战之部署论坛
  5. 详解:Linux Chrony 设置服务器集群同步时间
  6. sleep 与 wait 区别
  7. BZOJ2503: 相框
  8. HTML阅读打开点击不了,如何让网页文章中的代码可以点击运行
  9. 一些算法(最短路,线段树,01,完全背包,STL)的基本参考资料
  10. 孙正义辞任阿里董事 阿里:软银仍有权提名一名董事进董事会
  11. java实现工单派发_编写官方微信支付 Java SDK 的同学领下工单!
  12. 沟通CTBS助山东烟建实现财务数据大集中
  13. 常用的API函数汇总
  14. 值得收藏:程序员必去的社区与网站
  15. iOS 相机拍照与图库
  16. 深入探索 Android 网络优化(二、网络优化基础篇)上
  17. katalon错误: System could not generate internal.GlobalVariable file normally.
  18. 一分钟了解矩阵、方阵、对角矩阵、单位矩阵之间的关系
  19. 哈佛大学开放课程:《公正:该如何做是好?》1
  20. opensource项目_宣布2018年Opensource.com社区奖获奖者

热门文章

  1. python 自行安装第三方库包
  2. 中国学术会议(2009)---002
  3. 3c认证是什么,3c认证产品范围与认证材料
  4. C语言的除法运算:整除/和求余%
  5. 新手该学什么编程语言
  6. 第十一届蓝桥杯 ——成绩统计
  7. 实训计算机硬盘分区的心得体会,计算机实训报告
  8. 最新Chromedriver与Chrome版本对应参照表【附下载链接】
  9. 你一定不全知道的SAP凭证类型,我肯定!
  10. Mac下将文件复制到移动硬盘