Service启动和数据传递

Service是四大组件之一,Service是服务的意思,像Windows上面的服务一样,服务是在后台运行的,承担着静悄悄,默默的在后台付出的工作。

在开发过程中Service可以在很多地方使用,比如播放多媒体的时候用户启动了其他Activity ,这个时候程序要在后台继续播放;或者在后台记录用户地理位置的改变,或者启动服务来一直监听某种事件等。虽然Service存在的价值不如Activity,但是一般都让Service执行耗时时间较长的操作。下面我们详细介绍一下Service。

一,启动Service主要有两种方式:

  1)  startService(),调用者与服务之间没有关联,即时调用者退出,服务仍然可以运行。

    被启动的服务是由调用startService方法启动的,该方法会调用生命周期方法onStartComment(),当服务被启动后,改服务的生命周期与其他组件没有关系,即使启动服务的组件(Activity,BroadcastReciver)已经被销毁,该服务还是可以在后台无限期的运行,除非调用stopService()来停止服务。

2)  bindService(),调用者与服务绑定在一起,调用者一旦退出(启动Service的Activity退出,Service也退出),服务也退出。

    绑定服务是调用bindService方法启动的,绑定调用了onBind生命周期方法,改方法返回IBinder对象,同时启动服务的Activity必须提供ServiceConnect接口的实现类,它有两个方法onServiceConnected和onServiceDisconnected方法,监听Activity与服务类之间的连接。

二,Service的生命周期:

  

1、Started Service的生命周期:

  • onCreate():创建服务
  • onStartCommand():服务开始运行(在2.0以前版本中,使用onStart()回调方法)
  • onDestroy() :服务被停止

【详细说明:】

  • 在程序中调用:context.startService() 会触发执行Service生命周期中的onCreate()、onStartCommand()回调方法,此时服务就开始正式运行;
  • 如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand();如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand方法可能会重复调用多次;
  • 如果在程序中调用:context.stopService()会触发执行Service生命周期中的onDestroy()回调方法,会让服务停止;
  • stopService()的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService()的话,Service会一直在后台运行。该Service的调用者再启动该Service后可以通过stopService关闭Service;
  • 所以StartService的生命周期为:onCreate --> onStartCommand(可多次调用) --> onDestroy。

2、Bound Service的生命周期:

  • onCreate():创建服务
  • onBind():绑定服务,服务开始运行
  • onUnbind():取消绑定
  • onDestroy() :服务被停止

【详细说明:】

  • 在程序中调用:context.bindService()会触发执行Service生命周期中的onCreate()、onBind()回调方法,此时服务开始运行;
  • onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。此后调用者(Context,例如Activity)会和Service绑定在一起;
  • 如果调用Service的调用者Context退出了,那么会依次调用Service生命周期中的onUnbind()、onDestroy()回调方法,会让服务停止;
  • 所以BindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

三,绑定Service通信:

  1,向Service内部传递数据:

     创建一个Activity,用来启动Service,我们在Activity里面创建一个布局,如下所示:

      

   EditText用来动态改变向Service里面数据,点击同步数据按钮用来将Activity里面的数据传递到Service里面。

   将数据同步到Service里面需要利用服务得IBinder对象。下面是我的服务类:

public class MyService extends Service {

    private boolean running = false;
    private String data = "默认信息";//创建一个字符串,用来接收数据

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {    
        return new Binder();//④返回Binder的事例
    }

    /**
     *②创建一个类继承Binder,来对data数据进行更新
     */
    public class Binder extends android.os.Binder{
        public void setData(String data){//③写一个公共方法,用来对data数据赋值。
            MyService.this.data = data;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        running = true;
        new Thread(){  //①创建一个Thread用来数据传递进来的data数据。
            @Override
            public void run() {
                super.run();
                while (running){
                    System.out.println(data);//打印数据
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

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

在Activity中,需要实现ServiceConnection接口,并且在绑定成功的onServiceConnected方法中初始化Binder对象:

1,首先定义变量 private MyService.Binder binder = null;

2,在onServiceConnected方法中进行初始化:

@Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.Binder) service;
    }

3,点击同步数据按钮向Service里面赋值:

  binder.setData(editText.getText().toString());

具体代码如下所示:

public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {
    private EditText editText;
    private MyService.Binder binder = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        editText = (EditText) findViewById(R.id.edit);
        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unbindService).setOnClickListener(this);
        findViewById(R.id.btnSync).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bindService://点击绑定服务按钮
                bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService://解除绑定服务按钮
                unbindService(this);
                break;
            case R.id.btnSync://同步数据按钮
                if (binder != null){
                    binder.setData(editText.getText().toString());
                }
                break;
        }
    }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.Binder) service;
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}

这样就完成了想Service内部的数据传递。

四,service向Activity传递数据

 上面介绍了Activity向Service内部传值,现在我们来介绍一下Service向Activity传递数据:

 从Service向Activity传值,我们需要利用接口,首先在MyService里面自定义一个接口CallBack,实现onDataChanged方法;  

 public static  interface  CallBack{
         void onDataChanged(String data);
    }

在MyService里面定义CallBack类型的变量,并且实现它的set方法,来获得CallBack的实例。在MyService的Oncrate方法中定义一个变量i,然后动态改变i的数值,然后通过callback.onDataChanged("数据="+i) 将数据进行传递。具体实现方法如下所示:

public class MyService extends Service {

    private boolean running = false;

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new Binder();
    }

    /**
     *创建一个类继承Binder,来进行
     */
    public class Binder extends android.os.Binder{
        public MyService getService(){
            return MyService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        running = true;
        new Thread(){
            @Override
            public void run() {
                super.run();
                int i = 0;
                while (running){
                    i++;
                    if (callback != null){
                        callback.onDataChanged("数据="+i);
                    }
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

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

    private CallBack callback = null;

    public void setCallback(CallBack callback) {
        this.callback = callback;
    }

    public static  interface  CallBack{
         void onDataChanged(String data);
    }
}

在Activity中我们需要 1,获得Myservice的实例来调用serCallBack方法,所以我在MyService的Binder方法里面添加了获取MyService实例的方法。

2,将调用CallBack接口之后onDataChanged方法返回的值赋值到TextView上面,还是用到了servce的IBinder对象。

具体实现方法如下所示:

public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {

    private TextView textView;
    private MyService.Binder binder = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        textView = (TextView) findViewById(R.id.tvout);
        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unbindService).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bindService://点击绑定服务按钮
                bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService://解除绑定服务按钮
                unbindService(this);
                break;
        }
    }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.Binder) service;

        binder.getService().setCallback(new MyService.CallBack() {
            @Override
            public void onDataChanged(String data) {//因为在Service里面赋值data是在Thread中进行的,所以我们不能直接在这里将返回的值展示在TextView上。
                Message msg = new Message();
                Bundle bundle = new Bundle();
                bundle.putString("data",data);
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            textView.setText(msg.getData().getString("data"));
        }
    };
}

源码地址:

Activity向Service传递数据:http://download.csdn.net/detail/jingsummer/9372505

Service里面的数据传递到Activity中:http://download.csdn.net/detail/jingsummer/9372513

      

时间: 2024-12-25 17:46:42

Service启动和数据传递的相关文章

(Android数据传递)Service和Activity之间-- 借助BroadcastReceiver--的数据传递

实现逻辑如下: 左侧为Activity中的执行逻辑,右侧为Service中的执行逻辑: /** * <功能描述> Service和Activity之间的数据交互:具体表现为: 1. 从Service获取数据源,传递到Activity中: 2. * 在Activity中作数据更新: 3. Service中的onCreate()在UI线程中执行,作延时需要在子线程中执行: * * @author Administrator */ public class MainActivity extends

PCB MVC启动顺序与各层之间数据传递对象关系

准备着手基于MVC模式写一套Web端流程指示查看,先着手开发WebAPI打通数据接口,后续可扩展手机端 这里将MVC基本关系整理如下: 一.MVC启动顺序 二.MVC各层之间数据传递对象关系 原文地址:https://www.cnblogs.com/pcbren/p/9337766.html

Android应用开发-页面跳转与数据传递(重制版)

Android四大组件:Activity,Service,Broadcast Receiver,Content Provider 创建Activity 定义Java类,继承Activity类 在清单文件中配置activity标签 activity标签下如果带有下面这部分代码,则会在系统中多创建一个快捷图标 <intent-filter> <action android:name="android.intent.action.MAIN" /> <catego

Android页面跳转和数据传递

Android应用开发-页面跳转和数据传递 Activity Android四大组件之一 可以理解为Android中的界面,每一个界面都是一个Activity Activity的使用必须在清单文件中进行配置 在清单文件中, 创建第二个Activity 需要在清单文件中为其配置一个activity标签 标签中如果带有这个子节点,则会在系统中多创建一个快捷图标 <intent-filter> <action android:name="android.intent.action.M

无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

1.smartimageview使用 <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数据传递】全局变量的使用方法

[Android数据传递]全局变量的使用方法  印第安的老乔克 2013-02-18 21:36:14 android中Application是用来保存全局变量的,在package创建的时候就存在了,到所有的activity都被destroy掉之后才会被释放掉.所以当我们需要全局变量的时候只要在application中去实现,通过调用Context的getApplicationContext或者Activity的getApplication方法来获得一个Application对象,就可以设置或读

Intent的数据传递

虽然知识非常基础,但我觉得无论是否是难点,即便非常简单的知识,及时写出来对知识积累都是有好处的.今天写一下Intent的数据传递. 发送端: //创建Intent Intent intent = new Intent(); //把需要传递的内容放进Intent intent.putExtra("id", waitInfo.id); intent.putExtra("warnning_star", warnning_star); intent.putExtra(&qu

Android基础笔记(七)-页面跳转和数据传递

Activity简介 Activity的简单使用 Activity之间的跳转 意图传递数据 创建Activity获取返回数据 如何调用系统发送短信的页面 如何发送短信 Activity简介 Activity是Android的四大组件之一,它用于展示界面.它提供一个屏幕,用户可以用来交互,可以通过setContentView(View)来显示指定的控件. 在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应.Activit

activity间的数据传递

1.创建一个新的activity,然后在AndroidManifest.xml配置文件中完成声明. <application android:label="@string/app_name" android:icon="@drawable/ic_launcher"> <activity android:name="QuizActivity"android:label="@string/app_name">