Android——服务
服务(Service)是Android中实现程序后台运行的解决方案,他非常适用于去执行那些不需要和用户交互而且还要长期运行的任务。服务不依赖于任何用户界面,即使当前程序被切换到后台或者用户打开了另外一个应用程序服务仍能保持正常运行。
服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行 。
服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,
Android多线程编程
创建线程
Android多线程使用的都是基本的语法,定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面写耗时逻辑即可
使用继承方式定义一个线程
cless MyThread extends Thread{
@Override
public viod run(){
// 处理具体的逻辑
}
}
使用实现Runnable接口方式创建一个线程
class MyThread implements Runnable{
@Override
public void run(){
// 处理具体的逻辑
}
}
启动线程
使用继承方式创建一个线程
只需要New出 MyThread的实例然后调用它的start()方法,这样run()方法中的代码就可以在子线程中运行了。
new MyThread().start();
使用接口的方式创建一个线程
MyThread mtrhread = new Mythread();
new Thread(mythread).start();
服务的基本用法
服务是四大组件之一,
定义一个服务
新增一个类,并将其继承自Service
public class MyService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
注:onBind() 是Service中唯一的一个抽象方法,所以必须要在子类中实现,
如何里用服务中处理一些自己的代码逻辑,重写Service的另外一些方法。在不同时期做不同的事情。
public class MyService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() { // 创建时调用
super.onCreate();
}
@Override // 每次服务启动时调用
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() { // 销毁时调用
super.onDestroy();
}
}
onCreate()方法和 onStartCommand()方法的区别 :onCreate()方法是在服务第一次创建的时候调用的,而 onStartCommand()方法则在每次启动服务的时候都会调用,服务未创建过时,两个方法都会执行,之后就只有 onStartCommand()方法可以得到执行了。
每一个服务还要再AndroidManifest.xml (清单文件)文件中进行注册才能生效,这是四大组件共有的特点。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
........................
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
......................
</activity>
<service android:name=".MainActivity$MyService"> <!-- 注册服务 -->
</service>
</application>
</manifest>
至此,一个服务就完全定义好了。
启动服务和停止服务
启动和停止主要是借助**Intent(意图)**来实现的,
// 启动服务
Intent startIntent = new Intent(this,MyService.class);
startService(startIntent);
// 停止服务
Intent stopIntent = new Intent(this,MyService.class);
stopService(stopIntent);
注:类名.class其实时返回一个类的Class对象;
startService()和 stopService()方法都是定义在 Context 类中的,所以我们在活动里可以直接调用这两个方法。注意,这里完全是由活动来决定服务何时停止的,如果没有点击Stop Service 按钮,服务就会一直处于运行状态。 如果要让服务自己停下来,只需要在 MyService 的任何一个位置调用 stopSelf()方法就能让这个服务停止下来了 。
活动和服务进行通信
要在活动中指挥服务去干什么,需要借助我们刚刚忽略的 onBind()方法了。
例如:在MyService里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度,实现这个功能的思路是创建一个Binder对象来对下载功能进行管理。
public class MyService extends Service{
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder{
public void startDoenload(){
Log.d("Myservice", "startDoenload executed ");
}
public int getProgress(){
Log.d("Myservice", "getProgress executed ");
return 0;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/*
.............................
*/
}
新建了一个 DownloadBinder 类并让他继承自 Binder方法,在内部提供了下载以及查看进度的方法。并在onBind返回了这个实例。
实例
public class MainActivity extends Activity implements View.OnClickListener {
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
downloadBinder = (MyService.DownloadBinder) iBinder;
downloadBinder.startDoenload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// .....
bindService = (Button)findViewById(R.id.bind_service);
unbindService = (Button)findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bind_service:
Intent bindIntent = new Intent(this,MyService.class);
bindService(bindIntent,connection,BIND_AUTO_CREATE); // 绑定服务
break;
case R.id.unbind_service:
unbindService(connection); // 解绑服务
break;
default:
break;
}
}
创建了一个ServiceConnection 的匿名类,在里面重写了onServiceConnected()方法和 onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。在 onServiceConnected()方法中,我们又通过向下转型
得到了 DownloadBinder 的实例,有了这个实例, 我们可以在活动中根据具体的场景来调用 DownloadBinder 中的任何 public 方法。
活动与服务进行绑定是在BindService按钮的点击事件里完成的,先是构建出一个Intent对象,然后调用bindService方法,将MainActivity 和 MyService 进行绑定 ,bindService()方法接收三个参数,第一个参数就是刚刚构建出的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。这会使得 MyService 中的 onCreate()方法得到执行,但 onStartCommand()方法不会执行。
服务的生命周期
onCreate()、onStartCommand()、onBind()和 onDestroy()等方法都是在服务的生命周期内可能回调的方法。 如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。服务启动了之后会一直保持运行状态,直到 stopService()或stopSelf()方法被调用。注意虽然每调用一次 startService()方法,onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管你调用了多少次 startService()方法,只需调用一次 stopService()或 stopSelf()方法,服务就会停止下来了。
另外,还可以调用 Context 的 bindService()来获取一个服务的持久连接,这时就会回调服务中的 onBind()方法。类似地,如果这个服务之前还没有创建过,onCreate()方法会先于onBind()方法执行。之后,调用方可以获取到 onBind()方法里返回的 IBinder 对象的实例,这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开,服务就会一直保
持运行状态。
当调用了 startService()方法后,又去调用 stopService()方法,这时服务中的 onDestroy()方法就会执行,表示服务已经销毁了。类似地,当调用了 bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种情况都很好理解。但是需要注意,我们是完全有可能对一个服务既调用了 startService()方法,又调用了bindService()方法的,这种情况下该如何才能让服务销毁掉呢?根据 Android 系统的机制,一个服务只要被启动或者被绑定了之后,就会一直处于运行状态,必须要让以上两种条件同时不满足,服务才能被销毁。所以,这种情况下要同时调用 stopService()和 unbindService()方法,onDestroy()方法才会执行。