认识Service
Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。
其实大体上来讲,Service就是一个有一些功能的代码,然后前台Activity调用这个功能,让Service来运行起来!
两种Service启动方式
Service的有两种使用方式,一种是启动方式startService,另一种是绑定方式:bindService
他们有什么区别呢:
- 区别一:
- 启动方式,即使关闭了启动他前台,在后台依然运行,例如MP3;
- 绑定方式,只要关了其绑定的前台,后台就会关
- 区别二:
- 启动方式,不能在前台使用Service中的方法,
- 绑定方式,由于在前台可以获取到Service(后面会说),所以可以使用Service中的方法
生命周期
启动方式startService():
Service启动 -> onCreate() -> onStartCommand() -> onDestroy() -> Service已关闭
绑定方式bindService():
Service启动 -> onCreate() ->** onBind() -> onUnbind()** -> onDestroy() -> Service已关闭
不理解没关系,我们一步一步来看
service启动服务
我们再来看看service到底有些啥方法:onCreate(), onbind(),onStartCommand(), onDestroy()
onBind()
当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,必须返回 一个IBinder 接口的实现类,供客户端用来与服务进行通信。无论是启动状态还是绑定状态,此方法必须重写,但在启动状态的情况下直接返回 null。
onCreate()
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或onBind() 之前)。如果服务已在运行,则不会调用此方法,该方法只调用一次
onStartCommand()
当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。 如果自己实现此方法,则需要在服务工作完成后,通过调用 stopSelf() 或 stopService() 来停止服务。(在绑定状态下,无需实现此方法。)
onDestroy()
当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。
– 其实service里一般就这使用四个东西,你以后想要实现service,只要控制着四个方法就行
– 不过,onStartCommand一般不使用(重写),原因就是业务逻辑一般不再这里
– 一般业务简单的程序中,只需要重写onCreate(Service的业务),onbind(将该Service提供给外部,让外部可以来绑定他),以及提供给外部的方法
启动方式 startService()
然后我们来看看实战中的两种方式是如何使用的:
(我们这里就在在注释中解释啦)
Service
package com.zejian.ipctest.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class SimpleService extends Service {
/**
* 绑定服务时才会调用
* 必须要实现的方法
* @param intent
* @return
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。
* 如果服务已在运行,则不会调用此方法。该方法只被调用一次
*/
@Override
public void onCreate() {
System.out.println("onCreate invoke");
super.onCreate();
}
/**
* 每次通过startService()方法启动Service时都会被回调。
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand invoke");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服务销毁时的回调
*/
@Override
public void onDestroy() {
System.out.println("onDestroy invoke");
super.onDestroy();
}
}
调用Service的Activity
package com.zejian.ipctest;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.zejian.ipctest.service.SimpleService;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button startBtn;
private Button stopBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 按钮,控制Service的启动
startBtn= (Button) findViewById(R.id.startService);
// 按钮,控制Service的停止
// 如果不点这个按钮,那么Service就永远不会停止,即使关闭了当前页面
stopBtn= (Button) findViewById(R.id.stopService);
startBtn.setOnClickListener(this);
assert stopBtn != null;
stopBtn.setOnClickListener(this);
}
/**
* 点击按钮之后的事件
*/
@Override
public void onClick(View v) {
Intent it=new Intent(this, SimpleService.class);
switch (v.getId()){
case R.id.startService:
// 启动服务
startService(it);
break;
case R.id.stopService:
// 停止服务
stopService(it);
break;
}
}
}
绑定方式 bindService()
这个知识,我们以一个案例来讲:
- 在service中实现一个加法函数add(int x,int y)
- 并在Activity界面实现对service方法add的调用,实现加法计算。
- 在activity界面上有两个文本框输入数字,第三个文本框实现显示计算结果,一个button实现计算触发。
Service
package com.zjh.bindservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class AdditionService extends Service {
public class AdditionServiceBinder extends Binder {
AdditionService getService() {
return AdditionService.this;
}
}
private final IBinder binder = new AdditionServiceBinder();
/**
* 实现onbind方法
* 上面的AdditionServiceBinder,binder都是为这里服务的,大家以后可以将这个当成定式
*/
@Override
public IBinder onBind(Intent intent) {
return binder;
}
/**
* 提供给外部调用的类
*/
public int add(int x, int y) {
return x + y;
}
}
调用Service的Activity
package com.zjh.bindservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class AdditionActivity extends AppCompatActivity {
private AdditionService additionService;
private Button calculateButton;
private boolean isBound = false;
Intent intent;
/**
* 获取Service连接
* 这里大家也可以当做定式
*/
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
AdditionService.AdditionServiceBinder binder = (AdditionService.AdditionServiceBinder) service;
additionService = binder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText textView = findViewById(R.id.num1);
EditText textView2 = findViewById(R.id.num2);
TextView resultText = findViewById(R.id.result);
calculateButton = findViewById(R.id.button);
calculateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isBound) {
int num1 = Integer.parseInt(textView.getText().toString());
int num2 = Integer.parseInt(textView2.getText().toString());
int result = additionService.add(num1, num2);
resultText.setText("Result: " + result);
}
}
});
}
@Override
protected void onStart() {
super.onStart();
intent = new Intent(this, AdditionService.class);
// 调用绑定方法了
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (isBound) {
unbindService(serviceConnection);
isBound = false;
}
}
}
混合方式
同时使用启动方式和绑定方式,这样程序不仅可以绑定使用Service中的代码,也可以保持后台运行
其实就是按绑定方式的那一套来,但是启动的时候要使用startService(),剩下的和绑定Service一模一样
同样,我们结合一个案例来讲:
1、在service中实现随机数产生;
2、实现Service中的各个生命周期函数,并理解其功能;
2、在Activity界面实现随机数的显示,每2秒更新一次;
3、采用启动式完成service的启动;
RandomNumberService:
package com.zjh.exp;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.util.Random;
public class RandomNumberService extends Service {
private final IBinder binder = new RandomNumberBinder();
private Random random = new Random();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public class RandomNumberBinder extends Binder {
RandomNumberService getService() {
return RandomNumberService.this;
}
}
public int generateRandomNumber() {
return random.nextInt(100); // 生成0到99之间的随机数
}
}
RandomNumberActivity:
package com.zjh.exp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.widget.TextView;
public class RandomNumberActivity extends AppCompatActivity {
private TextView randomNumberTextView;
private Intent serviceIntent;
private Handler handler = new Handler();
private RandomNumberService randomNumberService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_random_number);
randomNumberTextView = findViewById(R.id.randomNumberTextView);
serviceIntent = new Intent(this, RandomNumberService.class);
startService(serviceIntent); // 启动Service
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (randomNumberService != null) {
int random = randomNumberService.generateRandomNumber();
randomNumberTextView.setText("随机数: " + random);
}
handler.postDelayed(this, 2000); // 每2秒更新一次
}
}, 2000);
}
@Override
protected void onStart() {
super.onStart();
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(serviceConnection);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
randomNumberService = ((RandomNumberService.RandomNumberBinder) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
randomNumberService = null;
}
};
}
好啦,我们这次的知识就讲到这里,如果觉得对您有用的话就点一个小小的赞吧!我们下次再见,拜拜