最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中Messenger原理及基本用法詳解

 更新時間:2017年03月16日 16:23:52   作者:ZhangJianIsAStark  
這篇文章主要為大家詳細介紹了Android中Messenger原理及基本用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下

這邊博客主要記錄一下Android中Messenger的基本原理和用法。

簡單來講,Messenger其實就是Binder通信的包裝器,是一種基于消息傳遞的進程間通信工具。

//Messenger實現(xiàn)了Parcelable接口,因此可以跨進程傳輸
public final class Messenger implements Parcelable {
 ...............
}

通常情況下,我們可以在A進程中創(chuàng)建一個Messenger,然后將該Messenger傳遞給B進程。
于是,B進程就可以通過Messenger與A進程通信了。

Messenger通常與Handler一起使用,我們看看對應(yīng)的源碼:

public final class Messenger implements Parcelable {
 private final IMessenger mTarget;

 public Messenger(Handler target) {
  mTarget = target.getIMessenger();
 }
 ...........
}

跟進一下Handler的getIMessenger函數(shù):

 .............
 final IMessenger getIMessenger() {
  synchronized (mQueue) {
   if (mMessenger != null) {
    return mMessenger;
   }
   //返回的是Handler中定義的MessengerImpl
   mMessenger = new MessengerImpl();
   return mMessenger;
  }
 }

 //此處MessengerImpl繼承自IMessenger.Stub
 //容易看出MessengerImpl將作為Binder通信的接收端
 private final class MessengerImpl extends IMessenger.Stub {
  public void send(Message msg) {
   msg.sendingUid = Binder.getCallingUid();
   Handler.this.sendMessage(msg);
  }
 }

從上述代碼可以看出,Messenger實際上作為了一個Binder服務(wù)端的wrapper。

當我們在A進程中創(chuàng)建Messenger,然后傳遞給B進程時,Messenger需要執(zhí)行Parcelable接口定義的操作,于是:

 //在A進程中將Binder信息寫入到Parcel中
 public void writeToParcel(Parcel out, int flags) {
  out.writeStrongBinder(mTarget.asBinder());
 }

 public static final Parcelable.Creator<Messenger> CREATOR
   = new Parcelable.Creator<Messenger>() {
  //在B進程中,重新創(chuàng)建Binder
  public Messenger createFromParcel(Parcel in) {
   IBinder target = in.readStrongBinder();

   //調(diào)用Messenger的另一個構(gòu)造函數(shù)
   return target != null ? new Messenger(target) : null;
  }

  public Messenger[] newArray(int size) {
   return new Messenger[size];
  }
 };

跟進一下Messenger的另一個構(gòu)造函數(shù):

public Messenger(IBinder target) {
 //得到的是Binder通信的客戶端
 mTarget = IMessenger.Stub.asInterface(target);
}

因此,當Messenger從進程A傳遞到進程B時,它就變?yōu)榱薆inder通信客戶端的wrapper。

當在進程B中使用Messenger的接口時:

public void send(Message message) throws RemoteException {
 //mTarget為Binder通信的客戶端,將消息發(fā)送給服務(wù)端的send函數(shù)
 //即服務(wù)端Handler的MessengerImpl的send函數(shù)
 //上文已經(jīng)附上了對應(yīng)代碼,可以看到對應(yīng)的消息將遞交給Handler處理
 mTarget.send(message);
}

以上就是Messenger通信的原理,現(xiàn)在實際測試一下。
我們定義一個簡單的demo,包含一個Activity和一個Service,其中Service與Activity處在不同的進程中。

AndroidManifest.xml中的定義如下:

  .....................
  <activity android:name=".MainActivity">
   <intent-filter>
    <action android:name="android.intent.action.MAIN"/>

    <category android:name="android.intent.category.LAUNCHER"/>
   </intent-filter>
  </activity>

  <service
   android:name=".RemoteService"
   android:enabled="true"
   android:exported="true"
   <!--指定服務(wù)運行在其它進程-->
   android:process=".remote">
  </service>
  ..............

Activity的界面很簡單,當點擊時就會像Service發(fā)送消息,Activity代碼如下:

public class MainActivity extends AppCompatActivity {
 private Button mButton;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  //打印Activity的pid及所在進程名稱
  Log.d("ZJTest", "Activity, pid: " + Process.myPid() +
    ", name: " + Util.getProcessName(this));

  //啟動服務(wù)
  startService();

  //綁定服務(wù)
  bindService();

  mButton = (Button) findViewById(R.id.test_button);
  mButton.setEnabled(false);
  //點擊按鍵后,利用Messenger向Service發(fā)送消息
  mButton.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    if (mMessenger != null) {
     try {
      Message msg = Message.obtain();
      msg.what = 1;
      mMessenger.send(msg);
     } catch (RemoteException e) {
      Log.d("ZJTest", e.toString());
     }
    }
   }
  });
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  unBindService();
  stopService();
 }

 private Intent mIntent;
 private void startService() {
  mIntent = new Intent(this, RemoteService.class);
  this.startService(mIntent);
 }

 private ServiceConnection mServiceConnection;
 private void bindService() {
  mServiceConnection = new LocalServiceConnection();
  this.bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
 }

 Messenger mMessenger;
 private class LocalServiceConnection implements android.content.ServiceConnection {
  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   //綁定服務(wù)后,獲得Messenger并激活Button
   mMessenger = new Messenger(service);
   mButton.setEnabled(true);
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   mButton.setEnabled(false);
  }
 }

 private void stopService() {
  stopService(mIntent);
 }

 private void unBindService() {
  unbindService(mServiceConnection);
 }
}

Service對應(yīng)的代碼如下:

public class RemoteService extends Service {
 private Messenger mMessenger;

 @Override
 public void onCreate() {
  super.onCreate();

  //同樣打印進程號及名稱
  Log.d("ZJTest", "Service, pid: " + Process.myPid()
    + ", name: " + Util.getProcessName(this));

  LocalHandler mHandler = new LocalHandler();

  mMessenger = new Messenger(mHandler);
 }

 private static class LocalHandler extends Handler{
  @Override
  public void handleMessage(Message msg) {
   Log.d("ZJTest", "receive msg: " + msg.what);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  //被綁定時,返回Messenger
  return mMessenger.getBinder();
 }
}

獲取進程名的代碼如下:

class Util {
 static String getProcessName(Context context) {
  int pid = Process.myPid();
  ActivityManager am = (ActivityManager) context
    .getSystemService(Context.ACTIVITY_SERVICE);

  for (ActivityManager.RunningAppProcessInfo appProcessInfo:
    am.getRunningAppProcesses()) {
   if (appProcessInfo.pid == pid) {
    return appProcessInfo.processName;
   }
  }

  return null;
 }
}

上述代碼都是比較簡單的,現(xiàn)在來看看運行結(jié)果:

02-20 21:25:15.760 D/ZJTest  (30460): Activity, pid: 30460, name: stark.a.is.zhang.messengertest
02-20 21:25:15.769 D/ZJTest  (30428): Service, pid: 30428, name: .remote
02-20 21:25:32.111 D/ZJTest  (30428): receive msg: 1

從log可以看出,Activity與Servie運行在不同的進程中,Messenger確實可以在不同進程間傳遞消息。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Android更改APP語言模式的實現(xiàn)過程

    詳解Android更改APP語言模式的實現(xiàn)過程

    本文詳細介紹如何更改Android中APP的語言模式,這個功能對于大家開發(fā)Android APP很有幫助,本文運用文字介紹和代碼示例把過程寫的很詳細,有需要的可以參考借鑒。
    2016-08-08
  • Android下拉刷新控件PullToRefresh實例解析

    Android下拉刷新控件PullToRefresh實例解析

    這篇文章主要為大家詳細解析了Android下拉刷新控件PullToRefresh實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android源碼學習之工廠方法模式應(yīng)用及優(yōu)勢介紹

    Android源碼學習之工廠方法模式應(yīng)用及優(yōu)勢介紹

    工廠方法模式定義:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類,感興趣的朋友可以了解下哦
    2013-01-01
  • Android實現(xiàn)萬能自定義陰影控件實例代碼

    Android實現(xiàn)萬能自定義陰影控件實例代碼

    這篇文章主要給大家介紹了關(guān)于Android實現(xiàn)萬能自定義陰影控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08
  • Android如何創(chuàng)建可拖動的圖片控件

    Android如何創(chuàng)建可拖動的圖片控件

    這篇文章主要為大家詳細介紹了Android如何創(chuàng)建可拖動的圖片控件,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Android?ASM插樁探索實戰(zhàn)詳情

    Android?ASM插樁探索實戰(zhàn)詳情

    這篇文章主要介紹了Android?ASM插樁探索實戰(zhàn)詳情,文章圍繞主題展開詳細的內(nèi)容戒殺,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 僅5步搞定Android開發(fā)環(huán)境部署 Android開發(fā)環(huán)境搭建教程

    僅5步搞定Android開發(fā)環(huán)境部署 Android開發(fā)環(huán)境搭建教程

    僅5步搞定Android開發(fā)環(huán)境部署,這篇文章主要為大家詳細介紹了Android開發(fā)環(huán)境搭建教程,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Android中Market的Loading效果實現(xiàn)方法

    Android中Market的Loading效果實現(xiàn)方法

    這篇文章主要介紹了Android中Market的Loading效果實現(xiàn)方法,較為詳細的分析了Android中l(wèi)oading效果的相關(guān)布局及功能實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • FragmentTabHost使用方法詳解

    FragmentTabHost使用方法詳解

    這篇文章主要為大家詳細介紹了Android中FragmentTabHost的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • flutter開發(fā)的app項目?打包成web

    flutter開發(fā)的app項目?打包成web

    如果你的Flutter版本低于2.0,請先升級Flutter版本,創(chuàng)建一個web文件夾來存放web相關(guān)的資源,使用HTML渲染器打包,該渲染器提供的打開速度最快,并且具有良好的瀏覽器兼容性,使用默認設(shè)置進行打包,提供的打開速度為一般,但依然保持良好的瀏覽器兼容性
    2024-08-08

最新評論

青田县| 宣武区| 泌阳县| 阿勒泰市| 丰宁| 苗栗县| 怀仁县| 资兴市| 广德县| 大渡口区| 南木林县| 贵德县| 张家川| 商南县| 宁夏| 富阳市| 杭锦后旗| 德安县| 全南县| 启东市| 吴川市| 横山县| 平潭县| 林西县| 龙南县| 天峨县| 庆城县| 仪陇县| 蒙自县| 盱眙县| 密山市| 新密市| 上思县| 太谷县| 铜陵市| 商城县| 临湘市| 普安县| 乌苏市| 油尖旺区| 克山县|