Service(服务)讲解与实例应用

什么是Service:

可以长时间运行在后台的不可见的没有界面的组件
运行在主线程中
可以跨进程调用

为什么要使用service

因为service是Android中实现程序后台运行的解决方案,非常适合那些不需要与用户进行交互且需要长期运行的任务。

service启动方式有哪些

startService和bindService两种

使用startservice启动服务

1.新建类继承Service
public class MyService extends Service {
2.重写onCreate(),用来数据的初始化,在服务没有停止之前,只会执行一次
 public void onCreate() {
        super.onCreate();
        Log.e(TAG+Thread.currentThread().toString(), "onCreate: " );

    }
3.重写onStartCommand(),用来接收调用者传递过来的参数,可以编写需要的逻辑代码

当重复调用Service时,会重复执行

    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
4.实现onBind()方法
  public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e(TAG, "onBind: " );
       throw new UnsupportedOperationException("Not yet implemented");
        //return mBinder;
    }
5.重写onDestroy(),做释放资源的操作
public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy: " );
    }
6.注册Service(在创建时会帮你实现)
<service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true">service>
7.在context环境中通过startService启动Service
startIntent = new Intent(MainActivity.this,MyService.class);
                this.startService(startIntent);
8.在context环境中通过stopService停止Service
this.stopService(startIntent);

实例讲解:

效果展现:点击启动服务和停止服务两次

Service(服务)讲解与实例应用_第1张图片
Service(服务)讲解与实例应用_第2张图片

可以看到虽然我点击了启动服务两次,但是,只执行了onCreate一次,但onStartCommand执行了两次,还有就是我点击了两次停止服务,但只执行了一次onDestroy方法,这原因我在介绍Service已经说过了,还可以看到的是,当服务停止时,线程并没有停止,这是因为子线程必须要执行完才会停止,不受服务关闭的影响,因为我在打印时同时打印了线程名,于是你可以看到,启动子线程的两个名字并不一样,且两个子线程各干各的,互不干扰

代码实现步骤:

1.在布局文件中完成控件的添加和id的设置,三四按钮暂时用不到
"http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.administrator.servicetest.MainActivity">

    id="@+id/main_et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    text=""
        android:gravity="center"
        android:textSize="30sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/main_tv"/>

    
2.创建自定义类继承Service重写方法
public class MyService extends Service {



    private static final String TAG = "MyService";

    public MyService() {

    }

   //重写onCreate(),打印
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG+Thread.currentThread().toString(), "onCreate: " );

    }
   //重写onStartCommand,打印,在里面写一个子线程,实现倒计时功能
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: " );
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=10;i>=0;i--){
                    Log.e(TAG+Thread.currentThread().toString(), "run: "+"----"+i);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
    //重写onBind()方法
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e(TAG, "onBind: " );
       throw new UnsupportedOperationException("Not yet implemented");
       // return mBinder;
    }
//    private DownloadBinder mBinder = new DownloadBinder();
//    class DownloadBinder extends Binder{
//
//        public void startDownload (){
//            Log.e(TAG, "startDownload: " );
//
//        }
//        public int getProgress(){
//            Log.e(TAG, "getProgress: " );
//            return 0;
//        }
//
//    }
    //重写onDestroy()
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy: " );
    }
}

在context环境启动服务
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button startBtn;
    private Button stopBtn;
    private Button bindBtn;
    private Button unBindBtn;
    private EditText editText;
    private TextView textView;
    private  Intent startIntent;

//    private MyService.DownloadBinder downloadBinder ;
//    private ServiceConnection connection = new ServiceConnection() {
//        @Override
//        public void onServiceConnected(ComponentName name, IBinder service) {
//            downloadBinder = (MyService.DownloadBinder) service;
//            downloadBinder.startDownload();
//            downloadBinder.getProgress();
//
//        }
//
//        @Override
//        public void onServiceDisconnected(ComponentName name) {
//
//        }
//    };


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

    private void bangID() {
        startBtn = findViewById(R.id.main_start_btn);
        stopBtn = findViewById(R.id.main_stop_btn);
        bindBtn = findViewById(R.id.main_bind_btn);
        unBindBtn = findViewById(R.id.main_unbind_btn);
        editText = findViewById(R.id.main_et);
        textView = findViewById(R.id.main_tv);

        startBtn.setOnClickListener(this);
        stopBtn.setOnClickListener(this);
        bindBtn.setOnClickListener(this);
        unBindBtn.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.main_start_btn:
                //启动服务
                startIntent = new Intent(MainActivity.this,MyService.class);
                this.startService(startIntent);
                break;
            case R.id.main_stop_btn:
                //关闭服务
                this.stopService(startIntent);
                break;
//            case R.id.main_bind_btn:
//                Intent bindIntent = new Intent(MainActivity.this,MyService.class);
//                this.bindService(bindIntent,connection,BIND_AUTO_CREATE);
//                break;
//            case R.id.main_unbind_btn:
//                unbindService(connection);
//                break;
            default:
        }
    }
}

对startservice启动服务的小节:

startservce使用特点:onCreate只会在创建service时执行一次,只要调用startService,onStartCommand一定会执行
startservice启动服务的优点:代码较为简洁,而缺点是,无法很好的控制服务,不能直接调用service中的方法,传值只能通过intent来传递。

使用bindservice启动service

效果展现:

Service(服务)讲解与实例应用_第3张图片

效果分析:可以看到我点击了三次绑定服务,和取消绑定,在打印中可以看到只打印了一段话,那是因为bindservice的特点:onCreate,onBind只会执行一次,这是通过在context环境中创建service对象调用的。

代码实现:

1.首先我们要修改Myservice中的代码
//重写onBind()方法,返回管家对象
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: ");
        //throw new UnsupportedOperationException("Not yet implemented");
        return guanjia;
    }

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

    //创建管家对象
    private Guanjia guanjia = new Guanjia();
    //使用bindservice启动service,需要在MyService中添加自定义类,继承Binder类,返回MyService.this
    //这里相当于创建了一个管家,获得了service的信任,以后就可以在context环境中通过管家获得service对象
    class Guanjia extends Binder {

        public MyService getServiceObject() {
            return MyService.this;
        }
    }
我还在MyService中添加了一个自定义方法,用以验证bindservice可以直接调用service中的方法
public void printDemo() {
        Log.e(TAG, "printDemo: " + "我挥舞着键盘,发誓要将这个世界写的明明白白");
    }
2.修改MainActivity中的代码:创建ServiceConnection的匿名内部类,在onServiceConnected()方法及活动与服务成功绑定时调用的方法,通过向下转型onbind()中传过来的service,在调用自定义方法,获得service对象,这样我们就可以为所欲为了,只要有了service的对象,就可以调用service中的public方法
 private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: " );
            MyService myService = ((MyService.Guanjia) service).getServiceObject();
            myService.printDemo();
        }

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


        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG, "onCreate: "+"++" );
        bangID();
    }

    private void bangID() {
        startBtn = findViewById(R.id.main_start_btn);
        stopBtn = findViewById(R.id.main_stop_btn);
        bindBtn = findViewById(R.id.main_bind_btn);
        unBindBtn = findViewById(R.id.main_unbind_btn);
        toBBtn = findViewById(R.id.main_to_b_btn);

        startBtn.setOnClickListener(this);
        stopBtn.setOnClickListener(this);
        bindBtn.setOnClickListener(this);
        unBindBtn.setOnClickListener(this);
        toBBtn.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.main_start_btn:
                //启动服务
                startIntent = new Intent(MainActivity.this,MyIntentService.class);
                this.startService(startIntent);
                break;
            case R.id.main_stop_btn:
                //关闭服务
                this.stopService(startIntent);
                break;
            case R.id.main_bind_btn:
                Log.e(TAG, "bindService: " );
                //启动绑定服务
                bindIntent = new Intent(MainActivity.this,MyService.class);
                /**
                 * param:1:intent对对象
                 * param2:serviceconnection实例
                 * param3:标志位,这里意思是自动完成绑定后自动创建服务
                 */
                this.bindService(bindIntent,connection,BIND_AUTO_CREATE);
                break;
            case R.id.main_unbind_btn:
                Log.e(TAG, "unbindService: " );
                //停止绑定
                unbindService(connection);
                break;
            case R.id.main_to_b_btn:
                Intent intent = new Intent(this,BActivity.class);
                startActivity(intent);
                break;
            default:
        }
    }
}

bindservice的特点:onCreate,onBind只会执行一次
使用优点:可以直接操作Service中的属性和方法。
缺点:创建service对象较为复杂

service的补充:IntentService

什么是IntentService

IntentService 是继承于 Service 并处理异步请求的一个类

IntentService的特点:

在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推

优点:

首先,我们省去了在 Service 中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止 Service

效果展现

Service(服务)讲解与实例应用_第4张图片
Service(服务)讲解与实例应用_第5张图片

效果分析,可以见到我点击了两次启动服务,按照之前的service,一到十的打印应该是互不影响,打印比较乱,可是在这个例子中,却看到子线程是排队打印的。

代码演示:

自定义类继承Intentservice,实现他的几个方法
public class MyIntentService extends IntentService{

    private String TAG = "MyIntentService";

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */

    public MyIntentService(String name) {
        super(name);
    }
    //重新建一个默认的构造方法,要没有参数
    public MyIntentService(){
        super("");

    }
    //重写onHandleIntent方法,可以看到我们可以直接进行耗时操作,那是因为服务自带子线程
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        for(int i = 10;i>=0;i--){
            Log.e(TAG, "onHandleIntent: " +i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }


}
最后添加执行语句就可以了。
 public void onClick(View v) {
        switch (v.getId()) {
            case R.id.main_start_btn:
                //启动服务
                startIntent = new Intent(MainActivity.this,MyIntentService.class);
                this.startService(startIntent);
                break;
            case R.id.main_stop_btn:
                //关闭服务
                this.stopService(startIntent);
                break;

最后我们来总结一下IntentService和Servce的区别:

service:Service 不是一个单独的进程,它和应用程序在同一个进程中,Service 也不是一个线程,它和线程没有任何关系,所以它不能直接处理耗时操作。如果有耗时操作就必须开启一个单独的线程来处理
IntentService: 是继承于 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推

你可能感兴趣的:(Android)