android之service(二)

来源:互联网 发布:怎样修改手机游戏数据 编辑:程序博客网 时间:2024/06/05 09:35

Service生命周期图:

左边是非绑定模式(启动模式),即通过Context.startService()来启动这个service;右边是绑定模式,即通过Context.bindService()来绑定这个service。两种模式既相对独立,又相互关联。

远程服务

远程Service,即通过Context.bindService()来绑定service。

定义一个service:RemoteService

package com.zzj.ui;import java.util.Timer;import java.util.TimerTask;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;public class RemoteService extends Service {private Timer timer;private TimerTask task;private int index; // 模拟service状态private MyBinder binder;public class MyBinder extends Binder {public RemoteService getService() {return RemoteService.this;}}@Overridepublic IBinder onBind(Intent intent) {System.out.println("onBind");return binder;}@Overridepublic boolean onUnbind(Intent intent) {System.out.println("onUnbind");return super.onUnbind(intent);}@Overridepublic void onCreate() {System.out.println("onCreate");binder = new MyBinder();timer = new Timer();task = new TimerTask() {@Overridepublic void run() {// System.out.println(Thread.currentThread().getName());index++;System.out.println(index);}};startTask();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {System.out.println("StartCommand");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {System.out.println("onDestroy");stopTask();super.onDestroy();}public int getStatus() {return index;}public void startTask() {timer.schedule(task, 1000, 1000);}public void stopTask() {timer.cancel();}}
定义一个绑定到上面service的service:RemoteService2
package com.zzj.ui;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;import com.zzj.ui.RemoteService.MyBinder;public class RemoteService2 extends Service {@Overridepublic IBinder onBind(Intent intent) {return null;}private static RemoteService2 remoteService2;private RemoteService remoteService;@Overridepublic void onCreate() {remoteService2 = this;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}/** * 获取实例 *  * @return */public static RemoteService2 getInstance() {return remoteService2;}/** * 启动 */public void startService() {Intent service = new Intent(RemoteService2.this, RemoteService.class);startService(service);}/** * 停止 */public void stopService() {Intent name = new Intent(RemoteService2.this, RemoteService.class);stopService(name);}/** * 绑定 */public void bindService() {Intent service = new Intent(RemoteService2.this, RemoteService.class);bindService(service, connection, BIND_AUTO_CREATE);}/** * 解绑 */public void unbinderService() {if (remoteService != null) {unbindService(connection);remoteService = null;}}/** * 获取状态 *  * @return */public Integer getServiceStatus() {if (remoteService != null) {return remoteService.getStatus();}return null;}private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("ServiceConnected2");MyBinder binder = (MyBinder) service;remoteService = binder.getService();}@Overridepublic void onServiceDisconnected(ComponentName name) {remoteService = null;}};public void onDestroy() {remoteService2 = null; // 防止内存泄漏unbinderService();};}
可以把RemoteService2是一个普通的组件,跟下面的activity一样,用来绑定到服务RemoteService。
定义一个activity:RemoteActivity
package com.zzj.ui;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;import com.zzj.ui.RemoteService.MyBinder;public class RemoteActivity extends Activity implements OnClickListener {private Button startBtn, stopBtn, bindBtn, unbindBtn, getServiceBtn,start2Btn, stop2Btn, bind2Btn, unbind2Btn, getService2Btn;private RemoteService remoteService;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("ServiceConnected");MyBinder binder = (MyBinder) service;remoteService = binder.getService();}@Overridepublic void onServiceDisconnected(ComponentName name) {System.out.println("ServiceDisconnected");remoteService = null;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.remote_activity);startBtn = (Button) findViewById(R.id.start);stopBtn = (Button) findViewById(R.id.stop);bindBtn = (Button) findViewById(R.id.bind);unbindBtn = (Button) findViewById(R.id.unbind);getServiceBtn = (Button) findViewById(R.id.get_service);start2Btn = (Button) findViewById(R.id.start2);stop2Btn = (Button) findViewById(R.id.stop2);bind2Btn = (Button) findViewById(R.id.bind2);unbind2Btn = (Button) findViewById(R.id.unbind2);getService2Btn = (Button) findViewById(R.id.get_service2);startBtn.setOnClickListener(this);stopBtn.setOnClickListener(this);bindBtn.setOnClickListener(this);unbindBtn.setOnClickListener(this);getServiceBtn.setOnClickListener(this);start2Btn.setOnClickListener(this);stop2Btn.setOnClickListener(this);bind2Btn.setOnClickListener(this);unbind2Btn.setOnClickListener(this);getService2Btn.setOnClickListener(this);Intent service = new Intent(RemoteActivity.this, RemoteService2.class);startService(service);}@Overrideprotected void onDestroy() {if (remoteService != null) {unbindService(connection);}super.onDestroy();}@Overridepublic void onClick(View v) {RemoteService2 remoteService2;switch (v.getId()) {case R.id.start:Intent i = new Intent(RemoteActivity.this, RemoteService.class);startService(i);break;case R.id.stop:Intent i2 = new Intent(RemoteActivity.this, RemoteService.class);stopService(i2);break;case R.id.bind:Intent i3 = new Intent(RemoteActivity.this, RemoteService.class);bindService(i3, connection, BIND_AUTO_CREATE);break;case R.id.unbind:if (remoteService != null) {unbindService(connection);remoteService = null;}break;case R.id.get_service:if (remoteService == null) {Toast.makeText(RemoteActivity.this, "Service is not binded!",Toast.LENGTH_LONG).show();} else {Toast.makeText(RemoteActivity.this,String.valueOf(remoteService.getStatus()),Toast.LENGTH_LONG).show();}break;case R.id.start2:remoteService2 = RemoteService2.getInstance();if (remoteService2 != null) {remoteService2.startService();}break;case R.id.stop2:remoteService2 = RemoteService2.getInstance();if (remoteService2 != null) {remoteService2.stopService();}break;case R.id.bind2:remoteService2 = RemoteService2.getInstance();if (remoteService2 != null) {remoteService2.bindService();}break;case R.id.unbind2:remoteService2 = RemoteService2.getInstance();if (remoteService2 != null) {remoteService2.unbinderService();}break;case R.id.get_service2:remoteService2 = RemoteService2.getInstance();if (remoteService2 != null) {if (remoteService2.getServiceStatus() == null) {Toast.makeText(RemoteActivity.this,"Service is not binded!", Toast.LENGTH_LONG).show();} else {Toast.makeText(RemoteActivity.this,String.valueOf(remoteService2.getServiceStatus()),Toast.LENGTH_LONG).show();}}break;default:break;}}}
该activity不仅用于绑定到RemoteService,也提供了操作RemoteService2的窗口。

xml文件:remote_activity.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:layout_width="300dp"        android:layout_height="wrap_content" >        <Button            android:id="@+id/start"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="start" />        <Button            android:id="@+id/stop"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="stop" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <Button            android:id="@+id/bind"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="bind" />        <Button            android:id="@+id/unbind"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="unbind" />    </LinearLayout>    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" >        <Button            android:id="@+id/get_service"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="getService" />    </LinearLayout>    <View        android:layout_width="fill_parent"        android:layout_height="2dp"        android:background="?android:attr/listDivider" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <Button            android:id="@+id/start2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="startByAnother" />        <Button            android:id="@+id/stop2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="stopByAnother" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <Button            android:id="@+id/bind2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="bindByAnother" />        <Button            android:id="@+id/unbind2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="unbindByAnother" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <Button            android:id="@+id/get_service2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="getServiceByAnother" />    </LinearLayout></LinearLayout>
界面:

首先定义两个概念:

1.Unbounded模式结束:调用了Context.stopService()或者Service.stopSelf();

2.Bounded模式结束:最后一个组件解绑,执行了onUnbind()方法。

使用不同的序列点击按钮,我们可以得到以下结论:

1.Unbounded模式生命周期:onCreate()、onStartCommand()、onDestroy()。

2.Bounded模式生命周期:onCreate()、onBind()、onUnbind() 、onDestroy()。

3.除了onStartCommand()方法,其他方法只会执行一次。

4.只有当第一个组件绑定到service时,才会执行onBind()方法;只有当最后一个组件解绑时,才会执行onUnbind()方法。

5.只要Bounded模式没有结束,即使调用Context.stopService()也不会销毁service。

6.只要Unbounded模式没有结束,即使最后一个组件解绑,也不会销毁service。


注意:如果一个组件绑定到了service,并且在组件销毁的时候没有解绑,系统会抛出错误。解决的办法是在组件的onDestroy()中解绑。


0 0
原创粉丝点击