Android开源项目SMSPopup学习 (三)

原文地址:Lucky_Man http://lucky-man.iteye.com/blog/954114

  在前两篇文章中,我们了解了SMSPopup的概况研究了目录结构和Mainfest文件 ,现在我们深入代码,来看看SMSPopup的具体实现。

   SMSPopupConfigActivity
   此类为程序入口,主要是SMSPopup的相关配置,该类继承了PreferenceActivity,该类是使用SharedPreferneces以键值对的形式保存相关配置数据的。
   在onCreate方法中,addPreferencesFromResource(R.xml.preferences);作用是从preferences.xml中加载PreferenceActivity的UI。
   preferences.xml中的元素有:
      PreferenceScreen        --xml顶层节点,若出现在子节点中,当点击此Preference时,会另外显示一屏
      PreferenceCategory        --代表一类相关的配置,用于分组
   以下四类为具体的Preference,依次是单选框,输入编辑框,列表选择,铃声选择。
      CheckBoxPreference       
      EditTextPreference
      ListPreference
      RingtonePreference
   程序就是通过这些基本的Preference来显示及更改配置信息的,也可以自定义Preference,定义类,继承上面几种Preference中的一种,在xml文件中引用即可,net.everythingandroid.smspopup.preferences包中的5个类都是自定义的Preference。

 

  SMSPopupUtilsService
    此类中利用了Android Message机制来使不同线程间通信。分析之前建议先了解下Android线程相关知识:http://zjf1428.iteye.com/blog/695491 ,文中详细描述了怎样使用Message、Handle、Looper相关类来完成线程间的通信。
    Android程序在启动时,系统会启动一个对应的主线程,主线程主要负责处理与UI相关的事件,Android UI操作并不是线程安全的并且这些操作必须在主线程中执行,这就引发了一个问题,当主线程正在做一些比较耗时的操作的时候,如正从网络上下载一个大图片,或者访问数据库,由于主线程被这些耗时的操作阻塞住,无法及时的响应用户的事件,从用户的角度看会觉得程序已经死掉,为增强用户体验,Android设置了一个5秒钟超时时间:一旦用户的事件由于主线程阻塞而超过5秒 钟没有响应,Android会 弹出一个应用程序没有响应的对话框。作为开发者,应当尽量避免在主线程中执行比较耗时的操作。来看看此类中是怎样做的:

Java代码 复制代码  收藏代码
  1. @Override  
  2. public void onCreate() {   
  3.     HandlerThread thread = new HandlerThread(Log.LOGTAG,    
  4.                            Process.THREAD_PRIORITY_BACKGROUND);   
  5.     thread.start();   
  6.     context = getApplicationContext();   
  7.     mServiceLooper = thread.getLooper();   
  8.     mServiceHandler = new ServiceHandler(mServiceLooper);      
  9. }   
  10.   
  11. Override   
  12. public void onStart(Intent intent, int startId) {   
  13.     //mResultCode = intent.getIntExtra("result", 0);   
  14.     Message msg = mServiceHandler.obtainMessage();   
  15.     msg.arg1 = startId;   
  16.     msg.obj = intent;   
  17.     mServiceHandler.sendMessage(msg);   
  18. }  
    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread(Log.LOGTAG, 
                               Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        context = getApplicationContext();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);   
    }
   
   @Override
    public void onStart(Intent intent, int startId) {
        //mResultCode = intent.getIntExtra("result", 0);
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

 

    此类继承了Service(后台服务),在onCreate()方法中,首先定义了一个HandlerThread,为ServiceHandler的创建准备Looper,Looper是MessageQueue和Handler之间的桥梁,具体参见上面的文章。再看onStart()方法,构造了一条Message,包含了一个intent对象,改intent来自于SMSPopupUtils调用startService(intent),intent中包含了一条SmsMmsMessage(短信实体)和Action(标志将短信设为已读的动作)。最后一句mServiceHandler.sendMessage(msg)执行完成后,Message就被转到Handler处理

Java代码 复制代码  收藏代码
  1. private final class ServiceHandler extends Handler {   
  2.      public ServiceHandler(Looper looper) {   
  3.          super(looper);   
  4.      }   
  5.        
  6.      @Override  
  7.      public void handleMessage(Message msg) {   
  8.          Log.v("SMSPopupUtilsService: handleMessage()");   
  9.          int serviceId = msg.arg1;   
  10.          Intent intent = (Intent) msg.obj;   
  11.          String action = intent.getAction();   
  12.            
  13.          if (ACTION_MARK_THREAD_READ.equals(action)) {   
  14.              Log.v("SMSPopupUtilsService: marking thread read");   
  15.              SmsMmsMessage message = new SmsMmsMessage(   
  16.                        context, intent.getExtras());   
  17.              message.setThreadRead();   
  18.          } else if (ACTION_OTHER.equals(action)) {   
  19.   
  20.          }   
  21.          finishStartingService(SMSPopupUtilsService.this, serviceId);   
  22.      }   
  23.  }  
   private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
       
        @Override
        public void handleMessage(Message msg) {
            Log.v("SMSPopupUtilsService: handleMessage()");
            int serviceId = msg.arg1;
            Intent intent = (Intent) msg.obj;
            String action = intent.getAction();
           
            if (ACTION_MARK_THREAD_READ.equals(action)) {
                Log.v("SMSPopupUtilsService: marking thread read");
                SmsMmsMessage message = new SmsMmsMessage(
                          context, intent.getExtras());
                message.setThreadRead();
            } else if (ACTION_OTHER.equals(action)) {
   
            }
            finishStartingService(SMSPopupUtilsService.this, serviceId);
        }
    }
 


    Handler类只有两个方法,一个构造方法,一个重写的handleMessage,用于处理sendMessage()发过来的消息,在handleMessage方法中,首先取出Message中包含的数据,根据Aciton做处理,此处Action表示将短信设为已读,由message.setThreadRead()完成。最后调用finishStartingService()停止Service并释放唤醒锁(释放CPU,使屏幕变暗)。
    实际上,在创建需要与用户界面交互的长时间运行的任务时,Android为我们提供了更简单的方法---使用AsyncTask类,具体用法见上面的文章,接下来动手改造SMSPopupUtilsService类,我们用简便的AsyncTask来替代Handler,改造过程比较顺利,就遇到一个把方法参数写错的小错误,改造后的代码确实比原来的简洁干净些。
    代码学习过程中,发现一处很有意思的地方:

Java代码 复制代码  收藏代码
  1. if (ACTION_MARK_THREAD_READ.equals(action)) {   
  2.   if (Log.DEBUG) Log.v("SMSPopupUtilsService: Marking thread read");   
  3.   SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());   
  4.   message.setThreadRead();   
  5. else if (ACTION_MARK_MESSAGE_READ.equals(action)) {   
  6.   if (Log.DEBUG) Log.v("SMSPopupUtilsService: Marking message read");   
  7.   SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());   
  8.   message.setMessageRead();   
  9. else if (ACTION_DELETE_MESSAGE.equals(action)) {   
  10.   if (Log.DEBUG) Log.v("SMSPopupUtilsService: Deleting message");   
  11.   SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());   
  12.   message.delete();   
  13. else if (ACTION_QUICKREPLY.equals(action)) {   
  14.   if (Log.DEBUG) Log.v("SMSPopupUtilsService: Quick Reply to message");   
  15.   SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());   
  16.   message.replyToMessage(intent.getStringExtra(   
  17.                           SmsMmsMessage.EXTRAS_QUICKREPLY));   
  18. else if (ACTION_UPDATE_NOTIFICATION.equals(action)) {   
  19.   if (Log.DEBUG) Log.v("SMSPopupUtilsService: Updating notification");   
  20.   updateNotification(intent);   
  21. }  
      if (ACTION_MARK_THREAD_READ.equals(action)) {
        if (Log.DEBUG) Log.v("SMSPopupUtilsService: Marking thread read");
        SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());
        message.setThreadRead();
      } else if (ACTION_MARK_MESSAGE_READ.equals(action)) {
        if (Log.DEBUG) Log.v("SMSPopupUtilsService: Marking message read");
        SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());
        message.setMessageRead();
      } else if (ACTION_DELETE_MESSAGE.equals(action)) {
        if (Log.DEBUG) Log.v("SMSPopupUtilsService: Deleting message");
        SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());
        message.delete();
      } else if (ACTION_QUICKREPLY.equals(action)) {
        if (Log.DEBUG) Log.v("SMSPopupUtilsService: Quick Reply to message");
        SmsMmsMessage message = new SmsMmsMessage(context, intent.getExtras());
        message.replyToMessage(intent.getStringExtra(
                                SmsMmsMessage.EXTRAS_QUICKREPLY));
      } else if (ACTION_UPDATE_NOTIFICATION.equals(action)) {
        if (Log.DEBUG) Log.v("SMSPopupUtilsService: Updating notification");
        updateNotification(intent);
      }
 

    请注意前两个判断,完全相同,也就是如果符合第一个条件,if里面的代码或执行两边,也就是将信息两次置为已读,完全多余,看了一下最新版本,代码还是如此。
    实际上参看AsyncTask的源代码 ,发现原来AsyncTask的实现竟然就是使用Handler Message机制,只是把它封装得更易用些,我们还是要熟练使用Message来处理线程间通信。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值