【Android开发基础】四大组件之一Service(服务)的应用场景及使用(以实时聊天为例)

文章目录

    • 一、引言
      • 1、什么是服务?
      • 2、应用场景
      • 3、其他类同
    • 二、生命周期
    • 三、基础使用
      • 1、创建服务
      • 2、注册服务
      • 3、启动服务
    • 四、进阶使用(实时聊天)
      • 1、实现效果
      • 2、数据流图
      • 3、服务部分

一、引言

1、什么是服务?

       Service(服务)是一种可以在后台长时间执行的运行操作,没有用户界面的应用组件。主要处理用户长时间不用的功能,但又不得不时刻在后台待命的一些指令。

2、应用场景

  • (1)网络事务:聊天(等待他人回复短信)、地图定位(熄屏后实时定位的播报语音)等
  • (2)本地资源:播放音乐(读取音乐文件)、文件IO(后台上传文件、下载文件)等
  • (3)定时任务:订单超时(未支付情况下,一定时间后自动销毁订单)、闹钟提醒等

3、其他类同

       根据我对其他框架的学习,类同的方法、组件都大同小异,就比如:

  • 前端(不用框架时):,就是定时器嵌套定时器
  • Vue:Web Socket
  • Spring:Spring Task

       其实这些组件、方法、库的设计思想和针对的问题都离不开一种设计模式 - Observer观察者模式(发布-订阅)
       主要是完成定时任务、通知反馈这类业务需求而存在。

二、生命周期

【Android开发基础】四大组件之一Service(服务)的应用场景及使用(以实时聊天为例)_第1张图片

  • onCreate() :
    首次创建服务时,系统将调用此方法。如果服务已在运行,则不会调用此方法,该方法只调用一次。

  • onStartCommand() :
    当另一个组件通过调用startService()请求启动服务时,系统将调用此方法。

  • onDestroy() :
    当服务不再使用且将被销毁时,系统将调用此方法。

  • onBind() :
    当另一个组件通过调用bindService()与服务绑定时,系统将调用此方法。

  • onUnbind() :
    当另一个组件通过调用unbindService()与服务解绑时,系统将调用此方法。

  • onRebind() :
    当旧的组件与服务解绑后,另一个新的组件与服务绑定,onUnbind()返回true时,系统将调用此方法。

三、基础使用

1、创建服务

简单写一个测试服务,每隔一秒打印一次时间。

public class TestService extends Service {

	//线程的声明
    private Thread thread = null;
    Calendar ca = null;

    @Override
    public void onCreate() {
        super.onCreate();
        // 公共时间对象
        ca = Calendar.getInstance();
        //创建服务时,创建线程对象
        thread = new Thread(null, background ,"TestThread");
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        if (!thread.isAlive()) {
            thread.start();
        }
    }

	/**
	*服务关闭时,销毁线程
	*/
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (thread.isAlive()) {
            thread.interrupt();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

	private Runnable background = new Runnable() {
        @Override
        public void run() {
            try{
                while (!Thread.interrupted()) {
                    int mYear = ca.get(Calendar.YEAR);
        			int mMonth = ca.get(Calendar.MONTH) + 1;
        			int mDay = ca.get(Calendar.DAY_OF_MONTH);
        			int mHour = ca.get(Calendar.HOUR_OF_DAY);
        			int mMinute = ca.get(Calendar.MINUTE);
        			time = mYear + "-" + mMonth + "-" + mDay + " " + mHour + ":" + mMinute;
        			Log.i("当前时间", time)
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

}

2、注册服务

如果不在AndroidManifest.xml里注册服务,使用后,应用启动会出现报错

【Android开发基础】四大组件之一Service(服务)的应用场景及使用(以实时聊天为例)_第2张图片


<service android:name=".service.TestService" />

3、启动服务

public class MainActivity extends AppCompatActivity {

	static Intent serviceTest = null;   // 测试服务
	
	 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       	init_service(getBaseContext())
    }

	private static void init_service(Context context) {
        serviceTest = new Intent(context, TestService.class);
        context.startService(serviceTest);
    }
    
}

四、进阶使用(实时聊天)

这里我会大致提供实现实时聊天功能的服务部分代码

1、实现效果

使用service实现的聊天功能

2、数据流图

很久没有画数据流图,有点生疏。

【Android开发基础】四大组件之一Service(服务)的应用场景及使用(以实时聊天为例)_第3张图片

3、服务部分

为了展示方便,我就将代码综合在一起了,没有分三层架构。

/**
 * 聊天服务
 */
public class ChatService extends Service {

    private Thread thread = null;      // 线程的声明
    static SqlChat sqlChat;            // 预显示聊天信息表
    static SqlChatInfo sqlChatInfo;    // 聊天信息内容表
    public static SqlFriend sqlFriend; // 好友信息表

    static String uid;                 // 当前用户ID,主要是用于定向连接服务器
    static String time;                // 当前时间

    static SharedPreferences user;

    @Override
    public void onCreate() {
        super.onCreate();
        // 公共时间
        Calendar ca = Calendar.getInstance();
        // 获取到用户ID
        user = getBaseContext().getSharedPreferences("user", MODE_PRIVATE);
        uid = user.getString("id", "");
        // 初始化数据库对象
        sqlChat = new SqlChat(getBaseContext(), uid);
        sqlFriend = new SqlFriend(getBaseContext(), Long.valueOf(uid).longValue());
        // 创建服务时,创建线程对象
        thread = new Thread(null, getChatInfo ,"ChatThread");
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        if (!thread.isAlive()) {
            thread.start();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //服务关闭时,销毁线程
        if (thread.isAlive()) {
            thread.interrupt();
        }
    }

    private Runnable getChatInfo = new Runnable() {
        @Override
        public void run() {
            try{
                while (!Thread.interrupted()) {
                    // 监听聊天信息 服务器控制层的@GetMapper("chat/{id}")
                    // id可以为雪花临时编号也可以是指定长久编号
                    String jsonChatInfo = okHttp.get(getBaseContext(), "chat/" + uid);
                    // 数据转换
                    Gson gson = new Gson();
                    Result<List<ChatInfo>> result = gson.fromJson(jsonChatInfo, new TypeToken<Result<List<ChatInfo>>>(){}.getType());
                    if (result.getCode() == 1) {
                    	int mYear = ca.get(Calendar.YEAR);
        				int mMonth = ca.get(Calendar.MONTH) + 1;
        				int mDay = ca.get(Calendar.DAY_OF_MONTH);
        				int mHour = ca.get(Calendar.HOUR_OF_DAY);
        				int mMinute = ca.get(Calendar.MINUTE);
        				time = mYear + "-" + mMonth + "-" + mDay + " " + mHour + ":" + mMinute;
//                        Log.i("service", result.getData().toString());
                        // 获取服务器存储的数据
                        for (ChatInfo chatInfo:result.getData()) {
                            insertChatInfo(getBaseContext(), chatInfo);
                        }
                    }
                    Thread.sleep(3000);   // 每隔三秒实现一次访问
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public static void insertChatInfo(Context context, ChatInfo chatInfo) throws IOException {
        // 初始化聊天信息数据库
        sqlChatInfo = new SqlChatInfo(context, uid, String.valueOf(chatInfo.getId()));
        Chat ch = sqlChat.select(Long.valueOf(chatInfo.getId()).longValue());
        Friend friend = sqlFriend.select(chatInfo.getId());
        // 异常判断
        if (friend == null)
            throw new IOException("短信指向异常");
//        Log.i("test", ch.toString());
        if (ch.getId() == null) {
            ch.setId(friend.getId());
            ch.setImage(friend.getImage());
            ch.setNotes(friend.getNotes());
            ch.setNext(chatInfo.getText());
            ch.setState(1);   // 参数state 0 -> 不显示 1 -> 显示(可以实现聊天信息删除以及数据恢复)
            ch.setService(1);
            ch.setTime(time);
            sqlChat.insert(ch);
        } else {
            ch.setId(friend.getId());
            ch.setNext(chatInfo.getText());
            ch.setService(ch.getService() + 1);    // 小红点加一
            ch.setTime(time);
            sqlChat.update(ch);
        }
        // 添加聊天信息
        ChatInfo chatInfo1 = new ChatInfo();
        chatInfo1.setId(friend.getId());
        chatInfo1.setState(1);
        chatInfo1.setText(chatInfo.getText());
        chatInfo1.setTime(time);
//        Log.i("test", chatInfo1.toString());
        if (sqlChatInfo.insert(chatInfo1)) {
            Log.i("insert", "ChatInfo添加成功!");
            ShowNotifications.showN(context, ch);
            if (UserInfoActivity.chatInfoViewModel != null) {   // 如果在聊天界面就更新数据
                UserInfoActivity.chatInfoViewModel.setListChatInfo();
            }
            if (ChatFragment.chatViewModel != null) {    // 如果在主界面Chat更新界面
                ChatFragment.chatViewModel.renew();
            }
        } else {
            Log.i("insert", "ChatInfo添加失败!");
        }
    }

}

你可能感兴趣的:(Android开发,android)