Android 中的一些线程操作

昨天看了看Android的线程文档,记录一些东西。

Android用的是J2SE,因此在其中的线程就是Java的线程。但是Android有自己的一套框架,因此线程的使用有一些新的东西。

活动与服务

在Android中,程序可以分成好几个组件,其中最重要的两个就是活动(Activity)和服务(Service)。活动是用户的GUI,而服务则运行于后台。比如说,一个IM,活动就是聊天的界面,而服务则用于网络通讯。

如果仅仅是这样的话,那么服务不过是一个没有界面的活动而已。但是实际上并非如此。为了节约资源,当一个活动不可见的时候,它是不会执行任何代码的,这时候就要靠服务了。例如在播放音乐的时候,就必须要用到服务,不然一切换到别的软件音乐就停了。

因此服务就给程序提供了后台运行的可能。更进一步的,服务是可以远程调用的,不只这个程序可以调用它,其他程序也可以调用它(前提是有相应的接口和权限)。

但是有一点要注意的是,同一个进程中的服务和活动是在同一线程中的。换句话说,后台和GUI是会相互阻塞的。这个和我的直觉有点出入,因为既然是后台服务嘛,怎么会阻塞到前台界面呢,但是事实就是如此。因此要在服务中执行长时间的操作(如网络应用)时,还是要自己创建线程来操作。

LooperHandlerThread

Android在Java的线程上又加了一层,使得线程拥有了消息队列(Message Queue)的支持。提供此支持的就是Looper。一个Looper负责执行一个消息循环,当消息队列里有消息时,处理消息,否则保持休眠。通常的GUI框架都会有消息循环与分发的概念,Android通过Looper将这个概念引入到了Java的线程中。通过它,只需要很少的代码就能为Java的线程加入这个功能:

  class LooperThread extends Thread {
      public Handler mHandler;
      
      public void run() {
          Looper.prepare();
          
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // 在此处理新消息
              }
          };
          
          Looper.loop();
      }
  }

其中重载Handler的handleMessage()方法来处理消息。

Android提供了HandlerThread类,这个类本身就是一个支持消息循环的线程类。

注意要启动一个线程还是需要手动调用start()的。

Handler

Handler是用于操作线程的消息队列的类。可以用空参数创建它,这样它就自动绑定到创建它的线程的消息队列上。也可以为它提供一个Looper,这样它就会绑定到Looper所在的线程上。Handler为不同线程之间的通信提供了方便。要和另外一个线程通信,只要得到它的Handler就行了。

对于上面的示例代码,mHandler就是绑定到新创建线程的Handler(因为run()是在新的线程中运行的)。对于一个HandlerThread,可以用getLooper()来得到它的Looper,但是要注意必须在这之前用start()启动了线程,不然是Looper是空的(文档上没说明这点,囧了我好一阵子)。

Handler的最大好处在于,它不只可以发送消息,还可以用post()来发送一个Runnable。这样一来,就可以在指定进程里面执行Runnablerun()方法中的代码了,也就是跨线程方法调用:)

另外,通过将Handler绑定到自己所在的线程,然后用post()方法,可以使一段Runnable里的代码不是立刻执行,而是在线程的消息队列轮到post过去的Runnable时才执行。不过我不明白这有什么用,还请高人指点。

Handler还可以指定消息/Runnable被处理的时间,这就可以把它当成定时器了(不过精确度不会太高吧)。

runOnUiThread()

当一个线程有结果了,要通知GUI更新呢?可以用ContextgetMainLooper()来得到主线程,然后用Handler操作。但是Activity类提供了一个简单的方法:runOnUiThread()。于是我们可以在线程中调用要更新的Activity的某个更新方法,在那个方法里用runOnUiThread(),将要运行的代码封装在一个Runnable里喂给它就行了。

以上就是目前所知道的Android里关于线程的一些方面,估计还有我不知道的东西,以后再说咯:P

android Comments(0) 2009年12月09日 21:11

hack了anfetion

AnFetion是Android上(唯一的?)飞信软件,支持了飞信上的基本功能,至少可以用来节省短信费:-)

但是这个软件有些不太完善的地方。之前申请加入开发,不过现在还没得到批准:(。

于是自己动手从最新的代码里fork了一个出来,自己hack了一个tsfetion

弄了三天,简单学习了一下android的开发,发现自己的java等于没学过。不过好在还是有一些成果滴:

  • 完善了消息通知机制,把有时从通知栏启动后,通知栏的通知不会消失,以及聊天对话框不会显示新消息的bug基本铲除了(应该是根除了吧,我想)
  • 还是消息通知机制,加入了对多个好友消息的支持,类似gtalk的效果
  • 加入了设置功能,可以设置新消息时的声音、振动和闪烁
  • 聊天消息采用列表方式显示,背景色区分自己与对方(还是抄gtalk的效果)
  • 修正了添加好友崩溃的bug

还有些是想做还没做的:

  • 好友切换(依旧是抄gtalk)
  • 解决时不时崩溃的bug(还不知道是什么原因造成的)
  • 聊天消息列表还无法用轨迹球滚动

改了不少地方,不知道会不会引入新的bug。

希望这些改动能被官方接受:P

android Comments(3) 2009年12月04日 22:06

简单试用Android下的三种输入法

今天看到QQ输入法也推出了android版本,突然有想试用其他输入法的冲动。于是索性把QQ输入法和搜狗输入法都下下来体验了一下。

以下是不完全体现感受:

  • 谷歌拼音
    • 优点
      • 方便修改输入错误
      • 整句输入
    • 缺点
      • 无9宫格键盘
  • 搜狗拼音
    • 优点
      • 垂直9宫格键盘,水平全键盘
      • 软键盘提供小工具
    • 缺点
      • 无整句输入
      • 手机键盘输入完成后屏幕有白条
      • 修改输入只能从后往前删
  • QQ拼音
    • 优点
      • 9宫格键盘
      • 笔划输入
    • 缺点
      • 无整句输入
      • 不能自动横屏全键盘
      • 全键盘热键太小,有数字键
      • 使用手机键盘输入时修选词没有数字标号
      • 开启手机键盘后轨迹球与非输入键无法使用
      • 修改输入只能从后往前删

从以上对比可以看出,谷歌拼音是为整句输入设计的,而搜狗拼音和QQ拼音是为字词输入设计的。我习惯了整句输入后用字词输入很不习惯。谷歌拼音android版(moopy)用的是和桌面版(goopy)相同的技术,整句输入是根据概率来选词的,只是词库和语言模型稍微小一点而已。

由于试用时间比较短,输入准确性不能用感觉判断,于是试了一句新闻:“台湾公布第三季增长率仍未逆转正”,谷歌拼音的输入感觉明显好过其它两个。不过平时使用的时候谷歌拼音也经常有牛头不对马嘴是现象,应该是手机版的词库和语言模型太小了。

由于搜狗和QQ拼音只是针对词组输入设计的,可能是目标用户输入串都不会太长,没有提供谷歌拼音那样直接向上可以修改输入串的功能。对我来说是不方便,不过对于�台词组输入来说影响应该不是很大吧。

搜狗和QQ最大的亮点是提供了9宫格软键盘。这点搜狗做得最好,可以自动在竖屏时使用9宫格,横屏时使用全键盘,非常方便。而且搜狗的软键盘提供了一个工具界面,可以直接用它来操作光标,选择/复制/粘贴,非常贴心的设计。QQ的软键盘比较傻,默认都是9宫格,横屏要手动切换成全键盘,而且全键盘因为直接包含数字键的关系,按键非常小,用起来不方便。谷歌拼音只提供了全键盘,横屏的时候按键很大,很舒服,但是竖屏的时候就只能是个摆设了。

其实9宫格输入已经可以算是另一种输入法了,重码比较多,用户体验需要重新设计。

另外QQ输入法不愧是beta版,直接使用G1键盘的体验非常差。它貌似截取了整个键盘,但是在非输入状态下没有把它不使用的按键释放出来,结果轨迹球、回车、空格等键在打开键盘时都不可用。另外一个最囧的情况就是开了键盘后候选词上没有数字标号,但是是可以用数字键选词的。就凭这两点就可以把它给打入冷宫了。相信正式版会改进这两个问题的。

在输入方式上,我还是喜欢谷歌拼音的整句输入。所以一番试用之后我还是换回了谷歌拼音。其实我想要谷歌拼音的整句输入+搜狗拼音的9宫格键盘啊……

android Comments(0) 2009年11月27日 19:27