@[toc]php
Android四大组件之一,没有界面的后台服务。咱们若是想要在后台执行一些任务,会用到Service。好比:后台下载更新;后台播放音乐等等。java
Service有两种启动方式,经过两种不一样的启动方式,生命周期执行方法也是不同的:android
startService:onCreate --> onStartCommand --> onStart ---> onDestroyapp
相对应的中止方法为:stopService异步
重复调用 startService 不会从新走 onCreate方法,只会走 onStartCommand --> onStartide
bindService: onCreate --> onBind ---> onUnBind ---> onDestroyoop
相对应的解绑方法为: unBindService源码分析
重复调用 bindService 方法,不会再次走 onCreate 方法,只会走 onBind 方法布局
混合启动:ui
service的onCreate只会走一次。
先调用 startService,再调用 bindService。 onCreate --> onStartCommand --> onStart --(此时调用 bindService )---> onBind。
先调用 bindService,再调用 startService。 onCreate --> onBind --(此时调用 startService )---> onStartCommand --> onStart。
混合启动想要销毁 Service 必须 stopService、unBindService 都调用,不然无效。
首先建立一个class继承Service
继承 service 的服务,在里面不能进行耗时操做,由于它自己也是依赖于主进程的,不是一个单独的线程,没法进行耗时操做。
public class MyService extends Service {
public static final String TAG = "MyService";
@Override
public void onCreate() {
Log.i(TAG, "onCreate: ");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "onStart: ");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
//在这里建立一个子线程,睡眠5秒钟后,调用关闭 service 方法
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
stopService1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
// 返回代理对象
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
public void stopService1() {
Log.i(TAG, "中止服务");
stopSelf();
}
public void receiveMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
//建立一个Service的代理类,经过它能够调用Service中的方法。
public class MyBinder extends Binder {
public void sendMsg(String msg) {
receiveMsg(msg);
}
}
}
复制代码
<!-- enabled 是否能够被激活,若是设置为false,就没法激活Service-->
<!-- exported 是否能够被外部*进程*激活,-->
<service android:name=".service.MyService" android:enabled="true" android:exported="false" />
复制代码
public class ServiceActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtnStartService;
private Button mBtnStopService;
private Button mBtnBindService;
private Button mBtnUnbindService;
private MyService.MyBinder myIBinder;
private MyConnection myConnection;
private Button mBtnCallService;//调用Service中的方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
initView();
initAction();
initData();
}
private void initView() {
mBtnStartService = findViewById(R.id.btn_start_service);
mBtnStopService = findViewById(R.id.btn_stop_service);
mBtnBindService = findViewById(R.id.btn_bind_service);
mBtnUnbindService = findViewById(R.id.btn_unbind_service);
mBtnCallService = findViewById(R.id.btn_call_service);
}
private void initAction() {
mBtnStartService.setOnClickListener(this);
mBtnStopService.setOnClickListener(this);
mBtnBindService.setOnClickListener(this);
mBtnUnbindService.setOnClickListener(this);
mBtnCallService.setOnClickListener(this);
}
private void initData() {
myConnection = new MyConnection();
}
@Override
public void onClick(View v) {
Intent service = new Intent(this, MyService.class);
switch (v.getId()) {
case R.id.btn_start_service:
startService(service);
break;
case R.id.btn_stop_service:
stopService(service);
break;
case R.id.btn_bind_service:
bindService(service, myConnection, BIND_AUTO_CREATE);
break;
case R.id.btn_unbind_service:
unbindService(myConnection);
break;
case R.id.btn_call_service:
myIBinder.sendMsg("我是Activity传来的消息");
break;
default:
break;
}
}
public class MyConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取Service的代理
myIBinder = (MyService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
复制代码
<?xml version="1.0" encoding="utf-8"?>
<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" tools:context=".service.ServiceActivity">
<Button android:id="@+id/btn_start_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="start_service" />
<Button android:id="@+id/btn_stop_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="stop_service" />
<Button android:id="@+id/btn_bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="bind_service" />
<Button android:id="@+id/btn_unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="unbind_service" />
<Button android:id="@+id/btn_call_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="调用Service内部方法" />
</LinearLayout>
复制代码
实验结果:
点击 bindService 绑定Service,而后点击 btn_call_service ,弹出吐司 “我是Activity传来的消息”,完成Activity和Service的调用
注意: Service是有可能绑定失败的,具体缘由和解决方案:bindService不调用onServiceConnected的问题
onStartCommand:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
复制代码
onStartComand使用时,返回的是一个(int)整形。
这个整形能够有四个返回值:start_sticky、start_no_sticky、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
它们的含义分别是:
START_STICKY:若是service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试从新建立service,因为服务状态为开始状态,因此建立服务后必定会调用onStartCommand(Intent,int,int)方法。若是在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,若是在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,若是在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后必定能重启。
flags表示启动服务的方式:
Additional data about this start request. Currently either 0,START_FLAG_REDELIVERY,or START_FLAG_RETRY。
START_FLAG_REDELIVERY:若是你实现onStartCommand()来安排异步工做或者在另外一个线程中工做, 那么你可能须要使用START_FLAG_REDELIVERY来让系统从新发送一个intent。这样若是你的服务在处理它的时候被Kill掉, Intent不会丢失.
START_FLAG_RETRY:表示服务以前被设为START_STICKY,则会被传入这个标记。
介绍
相对于Service而言,IntentService自己拥有一个子线程,能够进行耗时操做,在任务代码完成后,会自动销毁服务,不用手动调用。
代码:
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
}
多出一个onHandleIntent方法,能够在里面作耗时操做
@Override
protected void onHandleIntent(Intent intent) {
try {
Thread.sleep(5000);
Log.i(TAG, "onHandleIntent: 睡了5秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
}
复制代码
步骤:和Service同样,在 Activity 中调用 startService 方法开启服务。只不过 IntentService 在开启后,onHandleIntent 中的代码执行完后,会自动销毁服务。
实验结果:
2019-03-05 00:26:14.972 16106-16106/com.sjc.myapplication I/MyIntentService: onCreate:
2019-03-05 00:26:14.981 16106-16106/com.sjc.myapplication I/MyIntentService: onStart:
2019-03-05 00:26:19.983 16106-17272/com.sjc.myapplication I/MyIntentService: onHandleIntent: 睡了5秒
2019-03-05 00:26:19.985 16106-16106/com.sjc.myapplication I/MyIntentService: onDestroy:
复制代码
源码分析: IntentService源码并不长。
//自己是一个抽象类,继承与Service
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
//在内部建立了一个 Handler对象
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//执行完 onHandleIntent 方法后,调用了stopSelf方法,销毁服务。
onHandleIntent((Intent)msg.obj);
//销毁服务
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//在onCreate 中建立了一个 HandlerThread 线程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
//开启线程
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
//onStrat 中发送消息,而后回调ServiceHandler 的 handleMessage 方法
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
//退出Looper
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
//抽象方法,在子类中重写。
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
复制代码