安卓组件:Service

一、Service介绍: 

        在Android中,Service是一种可以在后台运行的组件,它可以执行长时间运行的操作,而不需要与用户交互。Service可以在应用程序的生命周期之外运行,即使用户切换到其他应用程序或锁定屏幕,Service仍然可以继续运行。

Service组件通常用于执行以下任务:

1. 后台播放音乐或音频文件
2. 下载或上传数据
3. 处理网络请求
4. 执行长时间运行的计算任务

Service组件有两种类型:

1. Started Service:这种Service是通过调用startService()方法启动的,它会在后台执行一些操作,直到任务完成或调用stopService()方法停止。Started Service不会自动停止,必须手动停止。

2. Bound Service:这种Service是通过调用bindService()方法启动的,它允许其他组件(如Activity)与Service进行通信。Bound Service会在所有绑定的组件都解绑后自动停止。

Service组件的生命周期包括以下方法:

1. onCreate():在Service创建时调用,用于初始化Service。
2. onStartCommand():在Service启动时调用,用于执行后台任务。
3. onBind():在Service绑定时调用,用于返回一个IBinder对象,以便其他组件可以与Service进行通信。
4. onUnbind():在Service解绑时调用,用于清理资源。
5. onDestroy():在Service销毁时调用,用于释放资源。

 

需要注意的是,Service运行在主线程中,因此如果执行耗时操作,应该在Service中创建一个新的线程来执行任务,以避免阻塞主线程。

二、服务启动方式

1、调用startService()方法启动服务:

MainActivity:

package com.example.handler;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button startService;
    private Button stopService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        startService = findViewById(R.id.bind_service);
        stopService = findViewById(R.id.unbind_service);
        stopService.setOnClickListener(this);
        startService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bind_service:
                Intent startIntent = new Intent(this,FirstService.class);
                startService(startIntent);
                break;
            case R.id.unbind_service:
                Intent stopIntent = new Intent(this,FirstService.class);
                stopService(stopIntent);
                break;
        }
    }
}

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="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=".MainActivity">
    <Button
        android:id="@+id/bind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="startService"/>
    <Button
        android:id="@+id/unbind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="stopService"/>
</LinearLayout>

 FirstService:

package com.example.handler;

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

import androidx.annotation.Nullable;

public class FirstService extends Service {
    private Thread mThread;
    private ServiceThread mServiceThread;
    private String TAG = "service";
    int i =0;
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate: ");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand: ");
        mServiceThread = new ServiceThread();
        mThread = new Thread(mServiceThread);
        mThread.start();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mServiceThread.flag = false;
        // 挂起线程
        mThread.interrupt();
        mThread = null;
        Log.i(TAG, "onDestroy: ");
    }


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

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


    private class ServiceThread implements Runnable{
        // 用volatile 修饰保证变量在线程间的可见性
        volatile boolean flag = true;
        @Override
        public void run() {
            while (flag){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Log.i(TAG, e.toString());
                    e.printStackTrace();
                }
                i++;
                Log.i(TAG, "run: 正常运行"+i);
            }
        }
    }
}

运行结果:

 2、使用bindService方式启动服务:

MainActivity:

package com.example.handler;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener{
    private Button bindService;
    private Button unbindService;
    private TextView mTextView,mHandlerText;
    private boolean flag = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initView();
    }
    private void initView() {
        mHandlerText = findViewById(R.id.handler_text);
        mTextView = findViewById(R.id.text);
        bindService = findViewById(R.id.bind_service);
        unbindService = findViewById(R.id.unbind_service);
        unbindService.setOnClickListener(this);
        bindService.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bind_service:
                Log.i("MainActivity", "onClick: ");
                Intent bindIntent = new Intent(this,SecondService.class);
                bindService(bindIntent,mServiceConnection, Context.BIND_AUTO_CREATE);
                flag = true;
                break;
            case R.id.unbind_service:
                if (flag){
                    unbindService(mServiceConnection);
                    flag = false;
                }else {
                    Toast.makeText(MainActivity2.this,"还没有绑定服务,不能解除绑定",Toast.LENGTH_LONG).show();
                }
                break;
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    private SecondService.MyBinder binder;
    private SecondService mSecondService;
    public ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 得到binder对象
            binder = (SecondService.MyBinder) service;
            // 给Service中message设置一个值
            binder.setData("MainActivity:");
            // 设置接口回调到获取Service中的数据
            mSecondService = binder.getService();
            mSecondService.setOnDataCallback(new SecondService.OnDataCallback() {
                @Override
                public void onDataChange(String msg) {
                  if (msg.equals("MainActivity:" + 10)){
                      Bundle bundle = new Bundle();
                      bundle.putString("name","小明");
                      Message msg1= mHandler.obtainMessage();
                      msg1.setData(bundle);
                      msg1.what = 1;
                      msg1.arg1 = 26;
                      mHandler.sendMessage(msg1);
                  }else if(msg.equals("MainActivity:" + 20)){
                      mHandler.sendEmptyMessage(2);
                  }else{
                      mHandler.post(new Runnable() {
                          @Override
                          public void run() {
                              mTextView.setText(msg);
                          }
                      });
                  }
                }
            });
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mSecondService = null;
        }
    };
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case 1:
                    String name = (String) msg.getData().get("name");
                    int age = msg.arg1;
                    mHandlerText.setText(name+"的年龄为:"+age);
                    break;
                case 2:
                    Toast.makeText(MainActivity2.this,"发送一个空的Message",Toast.LENGTH_LONG).show();
                    break;
            }
        }
    };
}

activity_main2:

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/bind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="startService"/>
    <Button
        android:id="@+id/unbind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="stopService"/>


    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Handler"
        android:gravity="center"
        android:textSize="26sp"/>
    <TextView
        android:id="@+id/handler_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Handler"
        android:gravity="center"
        android:textSize="26sp"/>


</LinearLayout>

SecondService:

package com.example.handler;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
/**
 * 以绑定的方式启动service
 */
public class SecondService extends Service {
    private String message;
    private boolean isRunning = true;
    private IBinder mIBinder = new MyBinder();
    private SecondService.ServiceThread mServiceThread;
    private Thread mThread;
    private String TAG = "SecondService";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"onBind");
        mServiceThread = new ServiceThread();
        mThread = new Thread(mServiceThread);
        mThread.start();
        /**
         * 返回一个可以在Activity的OnServiceConnected()方法中接收到的binder对象
         * 在Activity中通过这个bind对象可以得到Service的实例引用
         * 通过获取的Service实例就可以调用相关的方法和属性
         */
        return mIBinder;
    }

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

    }

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

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

    @Override
    public void onDestroy() {
        mServiceThread.flag = false;
        Log.i(TAG, "onDestroy: ");
        super.onDestroy();

    }


    public class MyBinder extends Binder{
      // 从Activity中传入msg值
        public void setData(String msg){
          SecondService.this.message = msg;
      }
        /**
         * 返回当前SecondService对象
         * 当Activity中获取binder类的实例化
         * 可以通过对此方法获取Service类实例
         */
      public SecondService getService(){
          return SecondService.this;
      }
    }

    private class ServiceThread implements Runnable {
        volatile boolean flag = true;

        @Override
        public void run() {
            Log.i(TAG, "run: 线程开始运行------");
            int i = 1;
            while(flag){
                if (mOnDataCallback!=null){
                    // 通过线程模拟真实场景,循环改变数据
                    mOnDataCallback.onDataChange(message+i);
                    i++;
                    try{
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }

    }
    private  OnDataCallback mOnDataCallback = null;
    public void setOnDataCallback(OnDataCallback mOnDataCallback){
        this.mOnDataCallback = mOnDataCallback;
    }
    public interface OnDataCallback{
        void onDataChange(String msg);
    }
}

 运行结果:

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值