Binder机制是android系统中跨进程通信的重要手段。其中,Service与Activity的交互通信使用到了这一机制。为此,我写了service的小案例,以此来方便更好地理解binder通信机制。
Service代码:
public class MyService extends Service { public boolean flag=true; int count; //实例化一个binder ServiceBinder serviceBinder=new ServiceBinder(); private static final String TAG = "MyService"; @Override public void onCreate() { Log.i("Winer","MyService is onCreate!"); //创建一个线程不断输出变化的count变量 new Thread(new Runnable() { public void run() { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { } //flag为true则count自加 if (flag) count++; //flag为flase则count自减 else count--; //输出count Log.i("MyService", "Count is" + count); } } }).start(); } @Override public boolean onUnbind(Intent intent) { Log.i("Winer","MyService is onUnbind!"); return super.onUnbind(intent); } @Nullable @Override public IBinder onBind(Intent intent) { Log.i("Winer","MyService is onBind!"); //返回binder return serviceBinder; } @Override public void onDestroy() { Log.i("Winer","MyService is onDestroy!"); super.onDestroy(); } //binder结构体,用于通信 class ServiceBinder extends Binder { public MyService getService() { return MyService.this; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("Winer","MyService is onStartCommand!"); return super.onStartCommand(intent, flags, startId); } }
MainActivity代码:
public class MainActivity extends AppCompatActivity { Button startBtn,changeBtn; MyService myService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建启动服务需要的intent final Intent i = new Intent(this,MyService.class); changeBtn= (Button) findViewById(R.id.change_btn); startBtn = (Button) findViewById(R.id.start_btn); startBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //创建并且绑定一个Service bindService(i, new ServiceConnection() { @Override //service连接上后所做的事情 public void onServiceConnected(ComponentName name, IBinder service) { //通过binder获取到service用来访问service的flag变量 myService = ((MyService.ServiceBinder) service).getService(); //利用按钮来改变flag changeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!myService.flag) myService.flag=true; else myService.flag=false; } }); } @Override //意外断开连接(如果程序正常退出不会执行该代码) public void onServiceDisconnected(ComponentName name) { } }, Context.BIND_AUTO_CREATE); } }); } }
最后别忘了在manifest里面注册service。
在了解binder之前,我们需要了解一下什么是Service。Service是安卓服务组件,类似于一个没有界面的Activity,常用于耗时服务进程,例如音乐播放器,下载器等。我们知道,activity与activity之间没有办法直接进行数据的交流。我们需要利用intent(binder机制的封装)来传数据。具体的方式为调用intent.putExtra(...)方法来放入intent中来启动activity。启动后,新的activity再重新获取这个数据。当然这样的方法也适用于启动Service。与activity不同的是,实际应用service与activity的交流更加频繁。例如音乐播放器,可能需要给音乐播放服务频繁发送播放、暂停、切换、快进等操作,服务也要及时返回播放进度等信息。因此,这种利用intent传递数据的方式显然是不合适的。因此,安卓直接使用了binder机制来传递信息。例如上方的代码,MainActivity是这样MyService的flag变量的:
1.通过bindService方法的参数ServiceConnection实例中onServiceConnected回调函数获取到了binder变量。
2.通过binder类中的返回值来获取MyService实例。
binder就好像一个service和activity之间的桥梁。activity先获取了binder实例,再利用binder实例获取到了Service实例。
下面我们一起来看下其内部逻辑的实现:
TinyMCE