Android四大组件之Service(一)

 Android系统中默默的劳动者—-Service在系统中扮演了一个很重要的角色,解决了实现程序后台运行的问题,这使得应用程序即使在关闭的情况下,也可以在后台继续执行一些后台任务。
 1.Service的适用场景
 Service是没有界面的,所以适用于不需要和用户交互而且要长期运行的任务,比如:QQ在关闭后仍然需要一个后台程序一直监听是否有收到消息,如果有就用将消息传递到Notification,在通知栏提示有新消息。
 2.Service的注意要点
 (1)服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行。
 (2)服务并不是运行在一个独立的进程中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序被杀死时,所有依赖于该进程的服务都会被停止运行。
 (3)虽然Service是在后台执行的,但Service并不会自动开启一个子线程去执行耗时操作,而是默认在主线程中执行。这就需要我们在自定义的Service内部开启子线程执行具体的任务(下面会有代码举例做法)。否则直接在主线程中执行耗时操作,容易引起主线程阻塞,导致ANR异常。
  (4)每个被创建的服务都是单例的,一个服务一旦被启动或者被绑定了之后,就会一直处于运行状态,只有当stopService()和unbindService()同时被调用,服务才会被销毁。
  (5)只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service。
 3.Service的生命周期及使用方法
 Service生命周期图
 上图是官方给出的Service生命周期方法的回调回程,每一个回调方法都代表了一个具体的Service状态。也可以看出根据启动方式分类可以分为两类:startServie()启动的Service(未和Activity绑定的Service)和bound Service(和Activity绑定的Service).
 下面总结每个生命周期方法时的特点:
 (1)onCreate():第一次创建服务时被回调,如果服务已经被创建过了就不再回调此方法。
 (2)onStartCommand():调用了Context的startService()方法,服务就会被启动,onStartCommand()就会被回调,所以这个回调方法是服务被启动时被系统回调的。启动之后会一直保持运行状态,直到stopService()或者stopSelf().并且每个服务只会存在一个实例,就像Activity的singleInstance(全局单例)模式一样.
 初次创建:onCreate()–>onStartCommand()–>onStart()
 已经创建过:onStartCommand()–>onStart()
 通常在此方法中编写逻辑代码。
 (3)onBind():调用Context的bindService()能获取一个服务的持久连接,这时会回调onBind()方法,如果此服务还未被创建:则onCreate()–>onBind()
 (4)onDestroy():服务被销毁时回调,也就是当调用了stopService()方法,onDestroy()会被执行。
 那么绑定的Service当执行了unbandService()之后也会回调onDestroy().
 问题:如果一个服务显示被startService()方式启动,后又调用bindService(),这种情况如何销毁服务呢?
 很简单,先取消绑定(unbindService()),再关闭该服务(stopService()或stopSelf())。
 具体实现代码举例如下(布局文件略):
 
Myservice.java:

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {
    final String TAG = "MyService-->";
    MyBinder myBinder;

    public MyService() {
        Log.d(TAG, "MyService: ");
    }

    //当一个活动和服务绑定后就可以调用该服务的Binder提供的方法了
    class MyBinder extends Binder {
        public void startOperate() {
            Log.d(TAG, "startOperate: -->");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        //throw new UnsupportedOperationException("Not yet implemented");
        return myBinder;
    }

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

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

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

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

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

MainActivity.java:

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.util.Log;
import android.view.View;

import static android.R.attr.onClick;

public class MainActivity extends AppCompatActivity {
    final String TAG = this.getClass().getSimpleName();
    MyService.MyBinder myBinder;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: ");
            //Binder implements IBinder
            myBinder = (MyService.MyBinder) service;
            myBinder.startOperate();
        }

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

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

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start:
                Intent intent = new Intent(this, MyService.class);
                startService(intent);
                break;
            case R.id.stop:
                Intent intent1 = new Intent(this, MyService.class);
                stopService(intent1);
                break;
            case R.id.bind_service:
                Intent bindService = new Intent(this, MyService.class);
                /*第一第二参数很好理解,第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可*/ 
                 bindService(bindService, connection, BIND_AUTO_CREATE);

                break;
            case R.id.unbind_service:
                unbindService(connection);
                break;
        }
    }
}

 4.IntentService的使用及与Service的差异
 Service作为后台服务的实现者,虽然是解决程序后台运行的问题,但是也是有不足需要补充的。比如没有向AsyncTask类似的异步操作方法,需要手动在onStartCommand()方法中开启新的线程执行耗时任务。还有就是在任务执行完毕后没有提供自动关闭的机制,需要手动去关闭。
 基于上述的不足,IntentService对Service做了很好的补充,IntentService继承于Service,官方介绍如下:
 IntentService官方介绍
 可以看出IntentService和Service的不同:
 (1)能处理异步请求;
 (2)开启新的工作线程完成耗时操作;
 (3)在操作完成后自动stop。
 下面列举IntentService的使用:
 

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

/**
 * created by zhiyuan at 2017/3/8
 */
public class MyIntentService extends IntentService {
    final String TAG = MyIntentService.class.getSimpleName();

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public MyIntentService() {
        super("MyIntentService");
    }

    //子线程中执行
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "onHandleIntent: current thread-->" + Thread.currentThread().getId());
    }

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

运行结果:
运行结果

猜你喜欢

转载自blog.csdn.net/yyg_2015/article/details/60872645