12.Android学习之Service应用(二)

本文深入探讨Android中的Service,讲解了Bound Service的绑定过程与使用,以及IntentService如何解决耗时操作的问题。同时,文章还分析了stopService()与stopSelf()的区别以及不同类型Service的特性。

目录

12.Service应用(二)

3.Bound Service

4.使用IntentService

5.难点解答

5-1.stopService()方法与stopSelf()方法的区别

5-2.不同类型Service之间的区别


12.Service应用(二)

3.Bound Service

当应用程序组件通过调用bindService()方法绑定到Service时,Service 处于绑定状态。多个组件可以同时绑定到一个Service上,当它们都解绑定时,Service被销毁。

如果Service仅用于本地应用程序并且不必跨进程工作,则开发人员可以编写自己的Binder 类来为客户端提供访问Service公共方法的方式。

注:这仅当客户端与Service位于同一个应用程序和进程时才有效,这也是最常见的情况。例如,音乐播放器需要将Activity 绑定到自己的Service来在后台播放音乐。

应用程序组件(客户端)能调用bindService()方法绑定到Service,该方法的语法格式如下:

bindService(Intent service, ServiceConnection conn, int flags)

参数说明:

◆service:通过Intent指定要启动的Service。

◆conn:一个 ServiceConnection 对象,该对象用于监听访问者与Service之间的连接情况。

◆flags:指定绑定时是否自动创建Service。该值设置为0时表示不自动创建,设置为BIND_AUTO_ CREATE时表示自动创建。

接下来Android系统调用Service 的onBind()方法,返回 IBinder 对象来与Service通信。

注:只有Activity、Service 和Content Provider能绑定到Service,BroadcastReceiver不能绑定到Service。

例:

 BinderService.java

package com.example.randonselectionnumber;
​
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
​
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
​
public class BinderService extends Service {
    public BinderService() {
    }
​
    //创建MyBinder内部类
    public class MyBinder extends Binder{
        public BinderService getService(){//创建获取Service的方法
            return BinderService.this;//返回当前的Service类
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return new MyBinder();//返回MyBinder Service对象
    }
    //自定义方法,用于生成随机数
    public List getRandomNumber(){
        List resArr = new ArrayList();
        String strNumber="";//用于保存生成的随机数
        for(int i=0;i<7;i++){
            //生成指定范围的随机整数
            int number=new Random().nextInt(33)+1;
            if(number<10){
                strNumber="0"+String.valueOf(number);
            }else {
                strNumber=String.valueOf(number);
            }
            resArr.add(strNumber);//把转换后的字符串添加到List集合中
        }
        return resArr;
    }
​
    @Override
    public void onDestroy() {//销毁Service
        super.onDestroy();
    }
}

MainActivity.java

package com.example.randonselectionnumber;
​
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
​
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
​
import java.util.List;
​
public class MainActivity extends AppCompatActivity {
    BinderService binderService;//声明Service类的对象
    //文本框组件ID
    int[] tvid={R.id.mian_tv1,R.id.mian_tv2,R.id.mian_tv3,R.id.mian_tv4,
            R.id.mian_tv5,R.id.mian_tv6,R.id.mian_tv7};
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionBar=getSupportActionBar();
        actionBar.hide();
​
        Button button=findViewById(R.id.main_btn1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                List number=binderService.getRandomNumber();
                for (int i=0;i<number.size();i++){
                    //获取文本框组件
                    TextView textView=findViewById(tvid[i]);
                    //显示生成的随即号码
                    textView.setText(number.get(i).toString());
                }
            }
        });
    }
​
    //创建ServiceConnection对象
    private ServiceConnection conn=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //获取后台Service
            binderService=((BinderService.MyBinder)iBinder).getService();
        }
​
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
​
        }
    };
​
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent=new Intent(MainActivity.this,BinderService.class);
        bindService(intent,conn,BIND_AUTO_CREATE);
    }
​
    @Override
    protected void onStop() {
        super.onStop();
        unbindService(conn);
    }
}

4.使用IntentService

IntentService是Service 的子类。

在介绍IntentService之前,先来了解使用Service 时需要注意的两个问题:

◆Service 不会专门启动一个线程来执行耗时操作,所有的操作都是在主线程中进行的,以至于容易出现ANR (Application Not Responding)的情况。所以需要手动开启一个子线程。

◆Service 不会自动停止,需要调用stopSelf()方法或者是stopService()方法来停止。

而使用IntentService,则不会出现这两个问题。因为IntentService在开启Service时,会自动开启一个新的线程来执行它。另外,当Service 运行结束后会自动停止。

例如,如果把在 2-1 小节中创建的MyService修改为继承IntentService,则可以使用下面的代码来模拟执行一段耗时任务,并测试其开启和停止。

package com.example.demo;
​
import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
​
import androidx.annotation.Nullable;
​
public class MyService extends IntentService {
    public MyService() {
        super("MyService");
    }
​
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.i("IntentService","Service已启动");
        //模拟一段耗时任务
        long endTime=System.currentTimeMillis()+5*1000;
        while (System.currentTimeMillis()<endTime){
            synchronized (this){
                try {
                    wait(endTime-System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
​
    @Override
    public void onDestroy() {
        Log.i("IntentService","Service已停止");
    }
}

Logcat面板将输出:

 从上面的代码中,可以看出使用IntentService执行耗时操作时不需要手动开启线程和停止Service。

5.难点解答

5-1.stopService()方法与stopSelf()方法的区别

stopService()方法执行后将直接执行onDestroy()方法进行Service的销毁;而stopSelf()方法执行后并不会立刻执行onDestroy()方法,而是等待onStartCommand()方法执行完才执行onDestroy()方法,进行Service的销毁。

5-2.不同类型Service之间的区别

普通Service不会专门启动一个单独的线程,所以不是在新创建的Worker线程中,就不应该在Service中直接处理耗时任务。Service 启动后在没有执行stopService()方法时,即使关闭当前应用后Service也将继续执行。销毁该应用资源后,Service 将自动停止。

Bound Service是当应用程序组件通过调用bindService()方法绑定到Service时,即可实现应用程序组件与Service之间的信息传递。解除绑定后将无法进行与Service的通讯。

IntentService是Service的子类,而IntentService将会使用列队来管理请求Intent,并开启一条新的Worker线程来处理该Intent。因此,IntentService 不会阻塞主线程,它可以自己处理耗时任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值