Android 主线程和子线程消息传递的一点心得

本文深入解析Android中消息机制及其在主线程与子线程间的通信原理,包括消息的处理流程、不同线程间消息传递的方式及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



 

/**
 * @author Evan 2014-11-19
 *
 * 消息的的星光大道
 * 不要界面,直接用日志打出来吧
 * 消息机制中各个概念的理解(官方的话,我就不说了,这里只写个人理解,个人把他们分别理解为行军打仗的两大阵营)
 * 主线程(甲方阵营)UIThread{
 * 成员介绍:
 * Hander :甲方司令       实例化myHander
 * Looper : 甲方信使      实例化Loooer.getMainLooper
 * MessageQueue  : 甲方信箱    消息队列
 * Message :  甲方信件
 *
 * }
 * 子线程(乙方阵营)SubThread{
 * 成员介绍:
 * Hander :甲方司令       实例化mySubHander
 * Looper : 甲方信使      实例化Loooer.getLooper,Looper.prepare;
 * MessageQueue  : 甲方信箱    消息队列
 * Message :  甲方信件
 *
 * }
 *
 * 技能介绍:(甲方,乙方都有)
 * Hander :司令官   召唤信使: 1.召唤己方信使 myHander.getLooper;getMainLooper  2.召唤乙方信使 SubThread.getLooper
 *               处理消息:handMessage
 *               读取信件:obtainMessage
 *               发送信件:sendMessage sendMessageToTarget  post(runnerable)
 * Looper :信使      收取指令: Looper.getLooper(Looper的归属就是那个司令官发的指令)
 *               整理信箱: Looper.prepare Looper.Loop;
 * MessageQueue: 信箱   存放Message
 *
 * Message 信件: 
 *
 *
 * */
public class MsgAvenueOfStars extends Activity {
 /*
  * 定义主线程消息处理句柄
  *
  * */
 private static MsgAvenueOfStars instance;
 
 private Handler mHandler;
 
 private Looper looper;
 
 public static MsgAvenueOfStars getInstance(){
  
     return  instance;
 }
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  instance = this;
  /**
   * 初始化主线程全局looper
   * */
  looper = getMainLooper();//或者Looper.myLooper();
  
  /**
   * 初始化主线程消息处理的执行者,即交给mhander处理
   * */
  mHandler = new MyHander(this,looper);
  
  /**
   * 主线程向自己发送消息
   *
   * */
  
  /**
   * 第一种方式
   * */
  Message msg1 = new Message();
  msg1.what = GlobalFinalStatic.CASE_ONE;
  msg1.obj = "我是从主线程发送的消息,我是case one";
  mHandler.sendMessage(msg1);
  /**
   * 第二种方式
   * */
  Message msg2 = mHandler.obtainMessage();
  
  msg2.what = GlobalFinalStatic.CASE_TWO;
  msg2.obj = "我是从主线程发送的消息,我是case two";
  mHandler.sendMessage(msg2);
  /**
   * 两种方法比较
   * new Message: 不管message池中有没有,都新建一个新的message实例
   * obtainMessage: 从官方源码上看,它是从后台调用obtain方法,从message池中返回已存在或则新建的message实例,从而能避免创建对象,减少内存的开销了。
   *
   * */
  
  
  /**
   * 主线程给子线程发送消息
   * case three 主线程把子线程的信使叫来,把消息交给子线程信使,让子线程的信使把消息交给子线程指挥官
   * 该方法几个要点
   * 1.子线程的信使要有子线程来任命,默认情况下子线程是没有信使的
   * 2.子线程要提供信使接口可以让主线程能够召唤该信使
   * 3.要使用稍微复杂点的线程知识,即,线程锁 ,当子线程的信使任命工作还没有完成时,要锁住线程,以免主线程在召唤时出现空指针的情况
   * */
  
  SubThreadOne subThread = new SubThreadOne(this);
  subThread.start();
  
  
  MySubHander mySubHander = new MySubHander(this, subThread.getLooper());
  Message subMessage1 = mySubHander.obtainMessage();
  subMessage1.what = GlobalFinalStatic.CASE_THREE;
  subMessage1.obj = "我是从主线程发出的消息,我命令子线程信使传递我的命令,我是case three";
  mySubHander.sendMessage(subMessage1);
  
  /**
   * 主线程给子线程发送消息
   * case four 主线程把子线程的指挥官叫来,直接命令指挥官执行命令
   * 
   *
   * */ 

  SubThreadTwo subThreadTwo = new SubThreadTwo(this);
  subThreadTwo.start();
  
  
  Message msg4 = mHandler.obtainMessage();
  msg4.what = GlobalFinalStatic.CASE_FOUR;
  msg4.obj = "我是从主线程发出的消息,我命令我的信使向子线程传递我的命令,我是case four";
  subThreadTwo.getHandler().sendMessage(msg4);
  

/**子线程给主线程发送消息*/
  SubThreadThree subThreadThree = new SubThreadThree(this);
  subThreadThree.start();
  
  /**
   * 那么这种hander和线程不在一起的写法,如何通知线程更新UI呢?,
   * 直接在hander的处理类中 调用MsgAvenueOfStars.getInstance().updateUI();
   * */
  
 }
 
 
 public void updateUI(){
  
 }



/**
 * 统一主线程处理消息类
 * */
public class MyHander extends Handler {
 private static final String TAG = MyHander.class.getSimpleName();
 private Context context;
 
 public MyHander(Looper looper){
  super(looper);
  
 }
 /**
  * 个人习惯每个类都定义多个构造函数,特别是这种带context句柄的,感觉特别好用,,喜欢写自己的东西的朋友应该深有体会
  * */
 public MyHander(Context context,Looper looper){
  super(looper);
  this.context = context;
  
 }
 
 @Override
 public void handleMessage(Message msg) {
  // TODO Auto-generated method stub
  super.handleMessage(msg);
  switch (msg.what) {
  case GlobalFinalStatic.CASE_ONE:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;
  case GlobalFinalStatic.CASE_TWO:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;
  case GlobalFinalStatic.CASE_FIVE:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;   
  default:
   break;
  }
 }


/**
 * 统一子线程处理消息类
 * */
public class MySubHander extends Handler {
 private static final String TAG = MySubHander.class.getSimpleName();
 private Context context;
 
 
 public MySubHander(Looper looper){
  super(looper);
 
  
 }
 /**
  * 个人习惯每个类都定义多个构造函数,特别是这种带context句柄的,感觉特别好用,,喜欢写自己的东西的朋友应该深有体会
  * */
 public MySubHander(Context context,Looper looper){
  super(looper);
  this.context = context;
  
 }
 
 @Override
 public void handleMessage(Message msg) {
  // TODO Auto-generated method stub
  super.handleMessage(msg);


  
  switch (msg.what) {
  case GlobalFinalStatic.CASE_FOUR:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;  
  case GlobalFinalStatic.CASE_THREE:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;
  case GlobalFinalStatic.CASE_ONE:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   
   //MsgAvenueOfStars.getInstance().updateUI();   通知Activity刷新UI
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break; 
  case GlobalFinalStatic.CASE_TWO:
   /*
    * LogUtils 自动以日志工具类
    *
    * */
   LogUtils.d(TAG, msg.obj.toString());//写到控制台
   
   LogUtils.writeToSd(context, msg.obj.toString());//写到sd卡文件
   
   break;    

  default:
   break;
  }
 }


public class SubThreadOne extends Thread {
 private final Object mLock = new Object(); 
 
 private Context context;
 
 private MySubHander mSubHander;
 
 private Looper subLooper;//子线程的信使
 
 private Looper mainLooper;//主线程的信使
 
 private String name = "subThread";
 
 public SubThreadOne(){
  
 }
 public SubThreadOne(Context context){
  this.context = context;
  Thread t = new Thread(null, this, name);
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();
        synchronized (mLock) {
            while (subLooper == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
  
 }
 
 /**
  * 该方法必须在线程启动后才能调用
  * */
 public Looper getLooper(){
  return subLooper;
 }
 
 
 
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  super.run();
  Looper.prepare();//实例化本线程的Looper对象,有个这句话,就表明该线程有了自己的信使
        synchronized (mLock) {
      
      subLooper = Looper.myLooper();//实例化信使,即任命subLooper为子线程的信使
            mLock.notifyAll();
        }  

  Looper.loop();
  
 }
 
 
    public void quit() {
     subLooper.quit();
    }


public class SubThreadTwo extends Thread {
 private final Object mLock = new Object(); 
 
 private Context context;
 
 private MySubHander mSubHander;
 
 private Looper subLooper;//子线程的信使
 private String name = "subThread"; 
 
 public SubThreadTwo(){
  
 }
 public SubThreadTwo(Context context){
  this.context = context;
  Thread t = new Thread(null, this, name);
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();  
        synchronized (mLock) {
            while (mSubHander == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
  
 }
 public SubThreadTwo(Context context,Looper looper){
  this.context = context;
  
 }
 
 /**
  * 该方法必须在线程启动后才能调用
  * */
 public Looper getLooper(){
  return subLooper;
 }
 
    public MySubHander getHandler() { 
        synchronized (mLock) {
            while (mSubHander == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
            return  mSubHander;
        }     
      
 }
 
 
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  super.run();
  Looper.prepare();//实例化本线程的Looper对象,有个这句话,就表明该线程有了自己的信使
        synchronized (mLock) {
         subLooper = Looper.myLooper();
         mSubHander = new MySubHander(context, Looper.myLooper());
         
            mLock.notifyAll();
        }  

  Looper.loop();
     

     
  
 }
 
 
    public void exit() { 
     getHandler().post(new Runnable(){ 
      public void run() { 
       Looper.myLooper().quit(); 
      }
     }); 
 }


public class SubThreadThree extends Thread {
 private final Object mLock = new Object(); 
 
 private Context context;
 
 private MySubHander mSubHander;
 
 private MyHander mSuperHander;
 
 private Looper subLooper;//子线程的信使
 
 private Looper mainLooper;
 private String name = "subThread"; 
 
 public SubThreadThree(){
  
 }
 public SubThreadThree(Context context){
  this.context = context;
  Thread t = new Thread(null, this, name);
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();   
        synchronized (mLock) {
            while (mainLooper == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
  
 }
 public SubThreadThree(Context context,Looper looper){
  this.context = context;
  
 }
 
 /**
  * 该方法必须在线程启动后才能调用
  * */
 public Looper getLooper(){
  return subLooper;
 }
 
    public MySubHander getHandler() { 
        synchronized (mLock) {
            while (mSubHander == null) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) {
                }
            }
            return  mSubHander;
        }     
      
 }
 
 
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  super.run();
  //Looper.prepare();//实例化本线程的Looper对象,有个这句话,就表明该线程有了自己的信使
        synchronized (mLock) {
         mainLooper = Looper.getMainLooper();
         //mSubHander = new MySubHander(context, mainLooper);
         mSuperHander = new MyHander(context,mainLooper);
         Message msg = mSuperHander.obtainMessage();
         msg.what = GlobalFinalStatic.CASE_FIVE;
         msg.obj = "我是从子线程发送的消息,我命令主线程的指挥官来执行我的命令,case five";
         mSuperHander.sendMessage(msg);
         
            mLock.notifyAll();
        }  
     

     
  
 }
 
 
    public void exit() { 
     getHandler().post(new Runnable(){ 
      public void run() { 
       Looper.myLooper().quit(); 
      }
     }); 
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值