Android Service总结

目录

 

1.Service 简介

2.Service 的生命周期

3.Service 的基本用法


1.Service 简介

       Service 是Android四大组件之一,它的作用是实现程序后台运行。它的运行不依赖用户界面,生命周期长。比如执行下载,音乐播放等任务。Service一般依赖于创建它的进程,一旦所依赖进程被杀死,Service也会停止执行。Service默认执行在主线程,当执行耗时操作时,需要在Service内部手动开启子线程,防止阻塞主线程。

 

2.Service 的生命周期

   

  在项目任何位置调用context的startService()方法,相应的服务就会启动起来,之后会一直保持运行状态,直到stopService()或者stopSelf()被调用。还可以调用context的bindService()方法来获得一个服务的持久连接,只要调用方跟服务之间的连接没有断开,服务就会一直保持运行状态。

  ①onCreate():当调用startService()或者bindService()时,如果这个Service之前没有创建过,onCreate()就会执行。

  ②onStartCommand():当调用startService()时,onStartCommand()方法就会回调,如果这个Service之前没有创建过,就会先执   行onCreate(),再执行onStartCommand()。每调用一次startService(),就会执行一次onStartCommand(),但每个服务只存在一个实例,只需调用一次stopService()或者stopSelf()方法服务就会停止。

③onBind():当调用bindService()时,onBind()方法就会回调,如果这个Service之前没有创建过,就会先执行onCreate(),再执行onBind()。可以获取onBind()中返回的IBinder对象的实例,自由地与服务通信。

④onDestroy():当调用startService(),再调用stopService(),onDestroy()就会执行,表示服务被销毁。当调用bindService(),再调用unBindService()也会执行。(注意:一个服务即调用了startService(),又调用了bindService(),这种情况下需要同时调用stopService()和unBindService(),onDertroy()才会执行)

 

3.Service 的基本用法

  新建一个Service,如下:

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

  MyService继承于Service,onBind()方法是Service中唯一一个抽象方法,必须在子类实现。我们可以再重写其他方法。

public class MyService extends Service {
    public MyService() {
    }
    @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();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

 如果我们希望服务一启动就执行某个动作,可以写在onStartCommand()方法里。我们也需要在onDestroy()方法里进行一些资源回收。注意记得在AndroidManifest.xml 文件中注册。

<service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>

我们设置两个按钮,一个来启动服务,一个来停止服务。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/start_service"
        android:text="Start"
        android:layout_marginTop="90dp"
        android:layout_marginStart="120dp"
        android:layout_width="120dp"
        android:layout_height="80dp" />
    <Button
        android:id="@+id/stop_service"
        android:text="Stop"
        android:layout_marginStart="120dp"
        android:layout_below="@id/start_service"
        android:layout_width="120dp"
        android:layout_height="80dp" />
</RelativeLayout>

  我们在MyService各方法中添加打印语句,来感受服务的执行。

public class MyService extends Service {
    public MyService() {
        Log.d("MyService","MyService()");
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyService","onCreate()");
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService","onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        Log.d("MyService","onDestroy()");
        super.onDestroy();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.d("MyService","MyService()");
        throw new UnsupportedOperationException("Not yet implemented");
        
    }
}

 活动代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    Button btStart;
    Button btStop;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btStart = findViewById(R.id.start_service);
        btStop = findViewById(R.id.stop_service);
        btStart.setOnClickListener(this);
        btStop.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.start_service:
                Intent startIntent = new Intent(this,MyService.class);
                startService(startIntent);  //开启服务
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this,MyService.class);
                stopService(stopIntent);  //结束服务
                break;
        }
    }
}

   点击start按钮,观察打印日志,onCreate(),onStartCommand()都执行了,多次点击,只有onStartCommand()执行。点击stop按钮,onDestroy()执行了。

我们也可以通过bindService()启动服务,获取onBind()中返回的IBinder对象的实例,自由地与服务通信。首先先在MyService中新建一个继承Binder的类,假设是一个对下载进行管理的类,在内部提供开始下载和查看下载进度的虚拟方法(打印一条语句)。并在MyService中创建它的实例,在onBind()中返回这个实例。代码如下:

public class MyService extends Service {
    private MyDownloadBinder mBinder = new MyDownloadBinder();
    class MyDownloadBinder extends Binder{
        public void startDownload(){
            Log.d("MyService","Start download");
        }
        public void getProgress(){
            Log.d("MyService","Get progress");
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
    }
.....
}

  在活动中将活动跟服务绑定,获取服务onbind()返回IBinder实例,就可以调用该服务里Binder的方法。代码如下:

public class SecondActivity extends Activity implements View.OnClickListener {
    Button btStart;
    Button btStop;
    private MyService.MyDownloadBinder binder;
    private ServiceConnection connection = new ServiceConnection() {
        //活动与服务成功绑定时调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyService.MyDownloadBinder)service;
            binder.startDownload(); //调用服务中Binder方法
        }
        //活动与服务解绑时调用
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        btStart = findViewById(R.id.start_service);
        btStop = findViewById(R.id.stop_service);
        btStart.setOnClickListener(this);
        btStop.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.start_service:
                Intent startIntent = new Intent(this,MyService.class);
                bindService(startIntent,connection,BIND_AUTO_CREATE);  //绑定服务,第3个参
                                                                       //数为标志位
                break;
            case R.id.stop_service:
                unbindService(connection);  //解绑服务
                break;
        }
    }
}

我们创建了一个ServiceConnection的匿名类,在onServiceConnected()方法中获得实例,在bindService中与服务绑定,这样活动就可以与服务进行通信。一个服务可以与多个活动进行绑定通信,绑定后所有活动都获得相同的实例。

上面的服务都运行在后台,我们无法感知,这时我们可以使用前台服务,因为前台服务会有一个正在运行的标志在系统状态栏显示,类似于通知的效果。通过修改MyService代码可实现前台服务。

public class MyService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);
        Notification notification = new Notification.Builder(this)
                                                    .setContentTitle("title")
                                                    .setContentText("text")
                                                    .setWhen(System.currentTimeMillis())
                                                    .setContentIntent(pendingIntent)
                                                    .build();
        startForeground(1,notification);

    }

    .....
}

  当我们在服务中执行耗时操作时,需要手动开子线程,当我们执行完想要服务停下来需要调用stopSelf()或者stopService()才能停下来。Androidt提供IntentService来方便我们,IntentService每次执行完都会自动停止,并且提供一个在子线程执行的方法给我们执行耗时操作。用法如下;

public class MyService extends IntentService {

    MyService(){
        super("MyService");
    }
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //耗时操作
    }
    .....
}

  我们可以在onHandleIntent()方法中执行耗时操作。这里先要提供一个无参构造函数,并且必须在其内部调用父类的有参构造函数。当执行完毕时,onDestroy()方法就会被调用。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值