xz0mzq 2012-02-15
这几天做了个Android手机与电脑连接的网络版五子棋,做的过程中感觉思路还蛮清晰的,结果最后测试的时候出现了一个问题:手机给电脑端发信息电脑都可以接收;而电脑往手机端传递信息时手机则只能接收一次信息,起初以为是通信协议的问题,但又觉得讲不通(如果是协议的问题,那么应该两边都会出现问题),不过还是一行行的System.out.println()测试了一遍,最后发现了一个现象:在手机端自定义的通信线程里一遇到与改动主界面组件有关的方法时线程就自动阻塞(像设置EditText文本信息,在主界面中弹出对话框等),期初一直百思不得其解,最后还是通过查看Logcat警告信息上网查阅,才明白了其中的原因(当时没有报错,就没有想着看WarnInfo),下面我简单的说下自己对Android中线程间信息的传递以及为什么需要信息传递的简单理解:
(一)Android开发遵循单线程模型,所谓单线程模型就是当系统开启一个程序时,系统会主动创建一个主线程(即UI线程),它负责程序界面时间的处理,例如屏幕触摸、屏幕画图、点击等事件。而如果程序需要执行一些耗时的操作时(如连接网络,下载数据、查询数据库等),主线程就会出现或长或短的阻塞现象(比如阻塞UI界面操作)。这样的机制肯定会造成应用软件的低效率。为解决这个问题,Android1开发包就引入了后台线程创建的API,主要有以下几种方法(这些都是在网上搜的,自己较熟悉的只有Handler类的使用):
接下来我就说下我对第四种方法使用的理解:
这种方法主要涉及到四个类:Message\Message Queue\Looper\Handler
首先Message Queue是信息队列,在主线程创建的时候会自动生成此类和将此队列中信息(Message类对象)传入Handler类的Looper对象。其他子线程需要专门创建其对应的Looper对象,这样说大家可能就明白了四者之间的关系了。
其次就是实现线程间信息传递的具体流程了:
其实很简单关键是创建Handler类对象(运用它的构造方法new Handler(Looper looper)),重写其中的HandlerMessage(Message msg)方法,这步中谨记构造方法中传入的Looper对象就是你要处理信息的线程对应的Looper,其中Looper有两个创建对象的方法;Looper.getMainLooper()获得主线程的Looper对象;Looper.myLooper()获得所在线程的Looper对象。之后即就是在你要传递信息的线程中创建Message对象,调用Handler的sendMessage(Message msg)方法,之中将你要传递的消息设置为Message的obj属性值。
(附:如果你在子线程中调用了更改UI界面的方法,那么会抛出calledWrongThreadException异常)
(二)现在想想为什么要运用单线程模型呢,原因是Android中的UI线程处理操作是不安全的,所以说凡是关于UI界面的操作必须是有主线程来执行,其他线程执行就会出现线程阻塞。
最后貌似还有不用这么麻烦的方法,Android中貌似有个类:AsyncTask,不过我这会对这个类还不是很熟悉,所以就不说了,大家有兴趣可以研究下,好了,终于又写了一篇博客了,心里比较安慰了,希望以后再接再厉,长久保持!!!