Android学习之Service生命周期及其通信

Service

Service是Android中的最重要的四大组件之一。

google官方给的定义是:

Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。

另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

Service的生命周期

注:与 Activity 生命周期回调方法不同,您不需要调用这些回调方法的超类实现。

我们可以写个MyService:

public class MyService extends Service {

    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate: ");
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: ");
        super.onDestroy();
    }
}

注册service:

<service android:name=".MyService"/>

布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="me.dengfengdecao.android.anotherservice.MainActivity">

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="startService"
        android:text="start Service"/>

    <Button
        android:id="@+id/stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="stopService"
        android:text="stop Service"/>

    <Button
        android:id="@+id/bind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="bind Service"/>

    <Button
        android:id="@+id/unbind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="unbindService"
        android:text="unbind Service"/>

</LinearLayout>

MainActivity:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Button mStartService;
    private Button mStopService;
    private Button mBindService;
    private Button mUnbindService;

    private Intent mIntent;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: ");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected: ");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mStartService = (Button) findViewById(R.id.start);
        mStopService = (Button) findViewById(R.id.stop);
        mBindService = (Button) findViewById(R.id.bind);
        mUnbindService = (Button) findViewById(R.id.unbind);

        mIntent = new Intent(this, MyService.class);
    }

    public void startService(View v) {
        startService(mIntent);
    }

    public void stopService(View v) {
        stopService(mIntent);
    }

    public void bindService(View v) {
        // 第一个参数指定要启动的service
        // 第二个参数指定服务连接的状态
        // 第三个参数指定只要存在绑定就会创建服务
        bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    public void unbindService(View v) {
        unbindService(mServiceConnection);
    }
}

启动,点击启动服务,日志如下:

此时,从正在运行的app中可以看到有一个服务启动了:

此时,停止服务,日志如下:

两种启动服务方式

startService

当应用组件(如 Activity)通过调用 ‘startService()’ 启动服务时,服务即处于“启动”状态。

  • 一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响。
  • 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。

例如,它可能通过网络下载或上传文件。 操作完成后,服务会自行停止运行。

如果组件通过调用 ‘startService()’ 并传递Intent对象启动服务,服务通过 ‘onStartCommand()’ 的调用接收Intent数据。
之后,服务将一直运行,直到服务使用 ‘stopSelf()’ 自行停止运行,或由其他组件通过调用 ‘stopService()’ 停止它为止。

bindService

当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。

绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。

  • 仅当与另一个应用组件绑定时,绑定服务才会运行。
  • 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

服务既可以是启动服务(以无限期运行),也允许绑定。通过实现回调方法:’onStartCommand()’(允许组件启动服务)和 ‘onBind()’(允许绑定服务)。

如果组件是通过调用 ‘bindService()’ 来创建服务(且未调用 ‘onStartCommand()’),则服务只会在该组件与其绑定时运行。一旦该服务与所有客户端之间的绑定全部取消,系统便会销毁它

NOte:默认情况下,服务与服务声明所在的应用运行于同一进程,而且运行于该应用的主线程中。为了避免影响应用性能,应在服务内启动新线程。

Activity和Service之间的通信

service通过onbind方法与activity进行绑定,实现通信。

MyService代码如下:

public class MyService extends Service {


    private static final String TAG = "MyService";

    private MyBinder mMyBinder = new MyBinder();

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate: ");
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return mMyBinder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand:每次点击启动服务按钮都会被调用。 ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: ");
        super.onDestroy();
    }

    class MyBinder extends Binder {
        public MyBinder() {
            super();
        }

        // 模拟后台下载
        public void download() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "run: 模拟下载");
                }
            }).start();
        }
    }
}

Activity代码如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Button mStartService;
    private Button mStopService;
    private Button mBindService;
    private Button mUnbindService;

    private Intent mIntent;
    private MyService.MyBinder mMyBinder;

    // 创建一个ServiceConnection匿名类
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: 与activity关联时调用");
            // 向下转型得到MyBinder实例
            mMyBinder = (MyService.MyBinder) service;
            // 调用后台服务进行下载
            mMyBinder.download();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected: 与activity解除关联时调用");
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mStartService = (Button) findViewById(R.id.start);
        mStopService = (Button) findViewById(R.id.stop);
        mBindService = (Button) findViewById(R.id.bind);
        mUnbindService = (Button) findViewById(R.id.unbind);

        mIntent = new Intent(this, MyService.class);
    }

    public void startService(View v) {
        startService(mIntent);
    }

    public void stopService(View v) {
        stopService(mIntent);
    }

    public void bindService(View v) {
        // 第一个参数指定要启动的service
        // 第二个参数指定服务连接的状态
        // 第三个参数指定只要存在activity关联到服务,就会创建服务
        bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    public void unbindService(View v) {
        unbindService(mServiceConnection);
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy: ");
        super.onDestroy();
    }
}

启动应用,绑定服务,日志输出如下:

此时,多次点击绑定服务按钮,没有日志输出。

点击解绑服务,日志如下:

Note:任何一个Service在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity建立关联,还可以和任何一个Activity建立关联,而且在建立关联时它们都可以获取到相同的MyBinder实例。

那如果我们既点击了Start Service按钮,又点击了Bind Service按钮结果又如何呢?我们实践下吧,重新启动应用,startService,日志如下:

继续点击bindservice按钮,日志如下:

这时,通过点击stopservice销毁服务,日志没有输出,再点下unbind,日志如下:

这个时候你会发现,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

Note:我们应该始终记得在Service的onDestroy()方法里去清理掉那些不再使用的资源,防止在Service被销毁后还会有一些不再使用的对象仍占用着内存。

如有不足请指出,谢谢!

参考:

http://blog.csdn.net/guolin_blog/article/details/11952435

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值