Android(安卓)线程通信,初见
Android 主线程与子线程之间的通信,子线程与子线程之间的通信
1.主线程发消息,子线程执行操作
其实一般情况下,主线程执行完所有必备逻辑后,再直接new Thread().start();(注意,没考虑内存泄漏),因为我们一般没有必要让子线程一直卡在某一步,等待消息后才执行,如果子线程不卡着,子线程执行完后自动结束。当然,新start的Thread我们要确定它什么时间执行还是比较麻烦的。但真的需要主线程发消息,子线程收到消息后执行操作,可以使用下面这个方法。
//先创建一个子线程HandlerThread handlerThread = new HandlerThread("name");//没看过源码,不知道参数具体作用,只知道是名字,类型为StringhandlerThread.start();//记得要开始线程/** * 注意,下面这才是重点(忽略我不规范的注释) * handler的handleMessage(Message msg)方法在哪一个线程执行,与handler在哪一个线程new没有关系,只与它所绑定的Looper有关, * 而Looper又与所在的线程绑定(一一对应),所以handler相当于与Looper身后的线程绑定。handler不带Looper参数的构造方法默认 * 与当前线程的Looper绑定,主线程默认配置Looper,而子线程需要调用Looper.prepare()后才被系统配置,因此子线程中handler的初 * 始化要放在Looper.prepare()和Looper.loop()(这是一个死循环)之间,基础不够扎实,还不知道找子线程中使用loop(),会不会造 * 成内存泄漏 */Handler mHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //这部分的操作都是在子线程中执行的 return false; }});
当然,也可以自定义一个thread类,提供一个接口出来,接口方法可以根据自身需求定义,thread里的run方法里是个死循环,然后主线程调用接口了,子线程才执行后面的操作(非常不推荐)
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyThread myThread = new MyThread(); OnMessageArrivedListener onMessageArrivedListener = myThread.getOnMessageArrivedListener(); new Thread(myThread).start(); //根据自己的时机调用 onMessageArrivedListener.onMessageArrived();}class MyThread implements Runnable{ private boolean hasArrived = false; private OnMessageArrivedListener onMessageArrivedListener = new OnMessageArrivedListener() { @Override public void onMessageArrived() { hasArrived = true; } }; public OnMessageArrivedListener getOnMessageArrivedListener(){ return onMessageArrivedListener; } @Override public void run(){ while(!hasArrived){} //下面执行子线程操作 }}interface OnMessageArrivedListener{ void onMessageArrived();}
可不可以用在主线程里使用的handler发送消息,自定义的子线程收到消息后再执行后续的操作呢?可以,就是有一点麻烦,需要在子线程拥有自身的Looper后,才可以,这就很麻烦了,尽管子线程可以直接把Looper或者handler开放出来,但主线程却不知何时才能使用它,这个强烈不建议使用。
2.子线程发消息,主线程执行操作
这个是最简单,也是用的最多的
我们可以在主线程创建一个全局的或者final修饰的handler对象,初始化之后,再调用newThread().start();然后在子线程中直接使用handler就可以了,非常简单方便
private Handler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //这里的操作在主线程执行 return false; } }); new Thread(new Runnable() { @Override public void run() { mHandler.sendEmptyMessage(1); } }).start();}
还有一种方式,就是在子线程里创建handler对象,前面说过,handler里handleMessage在哪个线程执行与在哪new无关,这种方式同样十分简单方便
new Thread(new Runnable() { @Override public void run() { Handler handler = new Handler(getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //这里的操作在主线程执行 return false; } }); }}).start();
3.子线程与子线程之间通信
个人建议是用主线程做中间媒介,一个子线程执行完了,发消息给主线程,主线程收到消息后再创建下一个子线程,相当于间接地实现了子线程与子线程之间的通信
如果你觉得这个不满意,我自己还想了一种方法,不过这方法我自己个人都不建议,建议去其他博客找更好的方法
这个方法跟之前提的也差不多,就是,两个子线程都引用同一个接口对象,在收消息的子线程创建接口实例对象,发消息的子线程执行完操作后调用这个接口的方法,方法根据自己需求定义,收消息的子线程因为引用相同的接口实例对象,从而达到获取消息的目的
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GetMessageThread getMessageThread = new GetMessageThread(); SendMessageThread sendMessageThread = new SendMessageThread(); //此时他们还只是个孩子。。。他们还只是一个类对象,还不是子线程 sendMessageThread.setOnMessageArrivedListener(getMessageThread.getOnMessageArrivedListener()); //执行完下面的代码他们就是了,注意顺序,尽管可能没什么用 new Thread(getMessageThread).start(); new Thread(sendMessageThread).start();}interface OnMessageArrivedListener{ void onMessageArrived(Object object);//所有都是自定义,可根据需求修改,返回值类型也是自定义}class GetMessageThread implements Runnable{ private boolean isOk = false; private OnMessageArrivedListener onMessageArrivedListener = new OnMessageArrivedListener() { @Override public void onMessageArrived(Object object) { //根据收到的消息决定isOk的值 //如 isOk = true; } }; //返回接口对象给发消息的子线程 public OnMessageArrivedListener getOnMessageArrivedListener(){ return onMessageArrivedListener; } @Override public void run(){ while (true){ if(isOk){ //执行操作 break; } } }}class SendMessageThread implements Runnable{ private OnMessageArrivedListener onMessageArrivedListener; public void setOnMessageArrivedListener(OnMessageArrivedListener onMessageArrivedListener){ this.onMessageArrivedListener = onMessageArrivedListener; } @Override public void run(){ //执行操作,根据需要的时机调用接口方法 Object o = new Object();//自己决定传什么 while(true){ if(onMessageArrivedListener != null){ onMessageArrivedListener.onMessageArrived(o); break; } } }}
这个方法因为我自身计算机系统基础不是很扎实,我自己都不知道会不会造成死锁,设计师说,这真的是糟糕透了!所以我也强烈不推荐这个方法
2019/5/8 留言:
没有修改博文,但还是要特别说一下,一定一定不要随随便便就用new Thread(),麻烦给Thread传一个名字啊,new Thread(CustonName)就好了,出现泄漏至少还能定位到哪里出的问题,不然你看到的只有Thread-1,Thread-2。。。
其实如果觉得比较麻烦,不妨试一下三方库EventBus,还是挺好用的,消息几乎哪里都可以达到
更多相关文章
- Android仿人人客户端(v5.7.1)——网络模块处理的架构
- Android开发:什么是IBinder
- Android(安卓)RxJava:细说 线程控制(切换 / 调度 )(含Retrofit实例讲
- android:framework了解一下
- [转]android消息机制,异步和多线程
- 如何去写Android(安卓)init.rc (Android(安卓)init language)
- Android(安卓)AsyncTask源码剖析
- android开发――通过子线程更新界面UI
- Android之入门:多线程更新UI界面