Android中服务(Service)的的生命周期,两种开启服务的方式的不同点,Service与Activity之间的通讯

工作内容:

1.Service的生命周期(bindService,startService的区别)

2.Service与Activity之间的通讯方式

学习分享:

准备:定义服务类继承自Service,在manifests中注册如下:(注册在application中与activity并列)


        

自定义服务类

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import org.greenrobot.eventbus.EventBus;

public class MyService extends Service {
    private MyBinder myBinder;
    public boolean isGo = true;
    private EventBus eventBus;
    private int x= 0;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        LogD.d("onBind");
        myBinder = new MyBinder();
        return myBinder;
    }
    //Android 2.2之后已被摒弃,建议使用onStartCommand
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        LogD.d("onStart");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        LogD.d("onCreate");
        eventBus =EventBus.getDefault();//初始化EventBus
        Intent intent = new Intent(this,SecoundActivity.class);
        PendingIntent pendIntent = PendingIntent.getActivity(this,0,intent,0);
        Notification noti = new Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("前台服务通知")
                .setContentText("点击跳转懂啊页面二")
                .setContentIntent(pendIntent)
                .build();
        startForeground(1,noti);//创建前台Service(在通知栏显示)
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogD.d("onStartCommand");
        /**
         * 正常情况下我们会在这里开启一条子线程来执行任务
         * 执行线程——Ui主线程
         */
        new Thread(){
            @Override
            public void run() {
                while (isGo){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    LogD.d("onStartCommand"+x++);
                }
                /**
                 * 在执行完之后这里使用了EventBus来将执行完毕的消息发送到Activity中
                 * 由此可想而知,也可以使用接口回调的方式来传递信息到Activity中,
                 * 但是要注意的是这里执行的是后台线程
                 */
                eventBus.post(new ServiceEvent("onStartCommand执行完毕"));
            }
        }.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        LogD.d("onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        LogD.d("onDestroy");
        isGo =  false;
        super.onDestroy();
    }
    class MyBinder extends Binder {

        public void startDownload() {
            LogD.d("执行Bindder类中的startDownload()");
            /**
             * 可以在这里开线程执行bandService的任务
             * 执行线程——Ui主线程
             */
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        LogD.d("startDownload:"+i);
                    }
                    eventBus.post(new ServiceEvent("startDownload执行完毕"));
                }
            }.start();
        }

    }
}
Activity.java代码
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btnStart,btnStop,btnBind,btnUnBind;
    private MyService.MyBinder myBinder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
        btnStart = (Button) findViewById(R.id.button);
        btnStop = (Button) findViewById(R.id.button2);
        btnBind = (Button) findViewById(R.id.button3);
        btnUnBind = (Button) findViewById(R.id.button4);
        btnStart.setOnClickListener(this);
        btnStop.setOnClickListener(this);
        btnBind.setOnClickListener(this);
        btnUnBind.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                //点击事件——触发开启服务
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent);
                break;
            case R.id.button2:
                //点击事件——触发停止服务
                Intent startIntent1 = new Intent(this, MyService.class);
                stopService(startIntent1);
                break;
            case R.id.button3:
                //点击事件——触发绑定服务
                Intent startIntent2 = new Intent(this, MyService.class);
                bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
                break;
            case R.id.button4://【应当用一个标识符来确定是否存在已绑定服务】【不判断——连续解绑会出错】
                //点击事件——取消绑定服务
                if(connection!=null&&myBinder!=null){
                    Intent startIntent3 = new Intent(this, MyService.class);
                    unbindService(connection);
                }else{
                    Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
                }

                break;
        }
    }
    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //取消绑定时调用
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定时掉用
            myBinder = (MyService.MyBinder) service;
            myBinder.startDownload();
        }
    };
    //接收Service中通过EventBus传过来的消息
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void showMsg(ServiceEvent event){
        Toast.makeText(this,event.getMsg(),Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}

一、Service的生命周期(bindService,startService的区别)

1.开启方式:startService

//点击事件——触发开启服务
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent);
.....
.....
//点击事件——触发停止服务
                Intent startIntent1 = new Intent(this, MyService.class);
                stopService(startIntent1);

执行生命周期:

注意:在onCreate之后重复点击开启Service,会重复执行onStartCommand,onStart方法,不会重复执行onCreate【注:onStart方法已被onStartCommand方法取代,不建议使用】

2.开启方式:bindService

 private ServiceConnection connection = new ServiceConnection() {//绑定需传入ServiceConnection实现类

        @Override
        public void onServiceDisconnected(ComponentName name) {//取消绑定时调用
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {//绑定时调用
            myBinder = (MyService.MyBinder) service;
            myBinder.startDownload();
        }
    };
....
....
//点击事件——触发绑定服务
                Intent startIntent2 = new Intent(this, MyService.class);
                bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
....
....
//点击事件——取消绑定服务
                if(connection!=null&&myBinder!=null){
                    Intent startIntent3 = new Intent(this, MyService.class);
                    unbindService(connection);
                }else{
                    Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
                }
执行生命周期: Android中服务(Service)的的生命周期,两种开启服务的方式的不同点,Service与Activity之间的通讯_第1张图片
注意:重复点击触发绑定事件并不会重复执行onBind方法

另外:

1.bindService和startService可以交叉使用,两者都使用,则需调用unbindService方法和stopService方法才会终止服务

2.无论开启多少次同一个Service,只需执行一次stopService/unbindService方法即可终止这个服务

3.我们应当在starService时就准备好在哪里stopService,在bindService时就准备好在那里unbindService

二、Service与Activity之间的通讯方式

1.在上方的bindService中可以发现我绑定之后会执行Bingdder类中的startDownload方法,这就实现了Activity中调用Service中的方法

2.我们也可以通过控制Service的生命周期的方式来实现简单的信息传递(本例中是控制Service的执行线程的isGo的值来终止其子线程继续执行)

3.可以在Service执行任务过程中通过EventBus.post()来将执行中的数据传送到Activity中(上面代码已经贴出)(EventBus需添加依赖/导包)

4.也可以使用回调的方式来将Service中执行任务的数据传送的Activity中(回调就不多说了,前面的章节有详细介绍)

执行效果:

执行线路1:【不调用stopService,即使退出app,服务也将继续执行】

点击执行startService——执行onCreate,onStartCommand(开始执行子线程[记数输出Log]),onStart;

点击执行stopService——执行onDestory(isGo=false),子线程接收到isGo=false之后终止执行——执行Activity中的showMsg方法;

执行线路2:【随着Activity生命周期结束而结束】

点击执行bindService——执行onCreate,onBind——执行Activity中的connection对象的onServiceConnected方法——执行Service中Binder子类的startDownload方法,执行子线程【应该用一个标识(boolean之类)来标识是否已在Activity中绑定了服务,不存在——不解绑,存在——解绑】

点击执行unbindService——执行onUnbind,onDestory

执行路线3:(请自行研究...)

点击执行startService

点击执行bindService

点击执行stopService

点击执行unbindService

三、实现在前台进程执行Service

由于后台Service可能会因为内存不足被系统回收,就可以创建前台Service主要是将Service显示在通知栏中

代码在上面的Servie中已经存在了,并注释(需要先会Notification的使用),这里只是简单实现了一个跳转,点击通知栏条跳转到app中的页面2

你可能感兴趣的:(Android基础)