Android知识程序员Android开发经验谈

Service基础知识

2018-01-14  本文已影响0人  yangchendev

Service是什么?

Service是一个一种能够长时间在后台运行并没有用户界面的应用组件。

Service和Thread的区别

Service翻译成中文就是“服务”,也许有人会认为服务就是能在后台执行耗时操作的,那就大错特错了,Service是运行在主线程的,如果超过20秒还未处理完成则Android系统就会报ANR错误,即应用未响应。
下面我们来验证一下,首先在Android Studio中创建一个MainActivity,再创建一个Service,在MainActivity中启动Service,并打印它们各自的所在的线程。

public class MainActivity extends BaseActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_main);
        //这里打印所在线程
        Log.d(TAG, "Thread is" + Thread.currentThread().getName());

    }

    @Override
    protected void initView() {

    }



    @Override
    protected void initData() {
        Intent intent = new Intent(MainActivity.this,MyService.class);
        startService(intent);
    }
}
public class MyService extends Service {
    private static final String TAG = "MyService";
    public MyService() {
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        //这里打印所在线程
        Log.d(TAG, "Thread is" + Thread.currentThread().getName());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

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

运行后的结果如下图。


2018-01-14_140359.png

可以看出Service确实是运行在主线程中的,那么我们就不应该在Service中执行耗时的操作了,应该在子线程中执行耗时的操作。

Service的启动方式

Service一共有两种启动方式,一个是startService,另一个是bindService

startService方法启动

这种方式启动service比较简单和启动一个activity差不多,步骤如下:

  1. 创建一个service,并在AndroidManifest文件中进行注册(使用Android Studio自动生成的可忽略)
  2. 在Activity中创建Intent intent = new Intent(MainActivity.this,MyService.class); startService(intent);
    具体代码如下:
public class MainActivity extends BaseActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "Thread is " + Thread.currentThread().getName());

    }

    @Override
    protected void initView() {

    }



    @Override
    protected void initData() {
        //启动服务
        Intent intent = new Intent(MainActivity.this,MyService.class);
        startService(intent);
    }
}

启动服务后依次会调用service中的onCreate->onStartCommand方法,其中onCreate只会调用一次,如果重新启动service的话,会重新调用onStartCommand方法。

onStartCommand方法的返回值

onStartCommand是有返回值的,返回值类型为int

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

通过看源码可以发现返回值有两个类型,分别是START_STICKY_COMPATIBILITY和START_STICKY

  1. START_STICKY_COMPATIBILITY:如果返回该值则不保证服务被杀死后会重新启动。
  2. START_STICKY:如果返回该值则服务在启动后被杀死会重新启动,会重新调用onStartCommand方法。
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
        onStart(intent, startId);
        return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
    }

默认返回的是START_STICKY。

在service内部给activity创建启动服务的方法

在看Tinker的源码过程中发现,可以在service内部给activity创建启动服务的方法,代码如下,这样的好处就是提高了代码的封装性。

 //对外提供启动servcie方法
    public static void runService(Context context) {
        try {
            Intent intent = new Intent(context, MyService.class);
            context.startService(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

bindService方法启动

bindService启动的service会将service与activity绑定,activity销毁了service也就停止了,步骤如下:

  1. 创建BindService服务端,继承自Service类,并在类中创建一个实现IBinder接口的实例对象并提供公共方法给客户端来调用。
  2. 从onBind方法回调方法返回此Binder实例
  3. 在客户端中,从onServiceConnected回调方法接收Binder,并使用提供的方法调用绑定服务。
    代码如下:
public class MyService extends Service {
    private static final String TAG = "MyService";
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // 返回IBinder对象
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Thread is " + Thread.currentThread().getName());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
    //给客户端提供服务的实例,从而可以来调用服务里的方法
    public class MyBinder extends Binder {

        public MyService getService(){
            return MyService.this;
        }
    }
    public void execute(){
        Log.d(TAG, "activity 调用 service 里的方法成功");
    }
}

public class MainActivity extends BaseActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "Thread is " + Thread.currentThread().getName());

    }

    @Override
    protected void initView() {

    }



    @Override
    protected void initData() {
        Intent intent = new Intent(MainActivity.this,MyService.class);
        //绑定服务
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);
    }

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //服务连接成功调用
            Log.d(TAG, "service 连接成功");
            MyService myService = ((MyService.MyBinder)service).getService();
            myService.execute();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //服务断开连接调用

        }
    };
}

运行结果如下图。


2018-01-14_144844.png

bindService执行的服务里方法的顺序如下:
onCreate->onBind->(Activity)onServiceConnected
通过绑定服务我们可以完成activity和service之间的通信,当然也可以使用广播。
欢迎大家来我的博客逛逛:http://yangchendev.top/

上一篇 下一篇

猜你喜欢

热点阅读