第一行代码(3)服务

作者: 官子寒 | 来源:发表于2019-12-21 16:30 被阅读0次

    服务Service是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务

    1.多线程编程

    1.1 线程的基本用法

    1. 继承 Thread
    class MyThread extends Thread{
        @override 
        public void run(){
        }
    }
    MyThread mThread = new MyThread();
    mThread.start();
    
    1. 实现Runnable接口
    class MyThread implements Runnable{
        @override 
        public void run(){
        }
    }
    MyThread mThread = new MyThread();
    new Thread(mThread).start();
    

    3.匿名类

    new Runnable(new Runnable{
        @override 
        public void run(){
        }
    }).start();
    

    1.2 在子线程中更新UI

    Android中的UI是线程不安全的,也就是说,如果想要更新程序里的UI元素,则必须在主线程中进行。但有时我们必须要在子线程里面执行一些耗时操作,对于这种情况,Android提供了一套异步消息处理机制,完美解决了问题。

    异步消息处理机制

    基本的异步消息处理机制总共分为3个步骤:

    1. 定义Handler
    private Handler handler = new Handler() {
    public void handleMessage(Message msg){
     switch(msg.what){
        case UPDATE_TEXT:
              //UI操作
    }}};
    
    1. 实例化Message对象
    Message msg = new Message();
    msg.what = UPDATE_TEXT
    
    1. handler发送消息
    handler.sendMessage(msg);
    

    1.2.1 Handler机制详解

    1. Message
    • 线程之间传递的信息,可携带少量的信息
    • 可以设置的字段有:objwhatarg1arg2
    1. MessageQueue
    • 消息队列,暂时存放消息
    • 串行执行
    • 每个线程只有1个MessageQueue
    1. Handler
    • 发送消息和处理消息
    1. Looper
      MessageQueue的管家,将MessageQueue中的消息取出,放入HandlerhandleMessage()
    异步消息处理机制

    1.2.2 AsyncTask
    AsyncTask是一个抽象类,需要继承使用

    可以传入3个泛型参数

    • Params 在执行AsyncTask时需要传入的参数,可用于在后台任务中使用
    • Progress 后台执行r任务执行时进度单位
    • Result 任务执行完毕的结果类型

    需要继承4个方法

    • onPreExecute()
      执行一些界面上的初始化操作,比如显示一个进度条对话框等
    • doInBackground(Params)
      处理所有的耗时任务,任务完成后可以用return将结果返回
      注意:这个方法不能进行UI操作
    • onProgressUpdate(Progress)
      在执行publishProgress(Progress)后,onProgressUpdate(Progress)就会被调用,可以来进行一些UI操作
    • onPostExecute(Result)

    启动

    new DownloadTask().execute();
    

    2.服务的基本用法

    2.1 定义一个服务

    1. 继承Service类
    public class MyService extends Service {
            public MyService(){}
            @Override
            public IBinder onBind(Intent intent){
                 }
    }
    }
    
    1. 实现方法
    • onCreate() 服务创建时调用
    • onStartCommand(Intent intent, int flags, int startId) 服务启动时调用
    • onDestroy()服务销毁时调用

    3.注册Service

    <Service
    android:name = ".MyService"
    android:enabled="true"
    android:exported="true">
    </Service>
    

    2.2 启动和停止服务

    1. Intent开始和启动
    Intent startIntent = new Intent(MainActivity.this, MyService.class);
    startService(startIntent); //Context类
    // stopService(startIntent);
    
    1. 自己停止
      stopself() 调用后能让服务停止下来

    2.3 活动和服务进行通信

    步骤:
    1.在服务中创建内部类downloadBinder继承至Binder,主要实现一些方法
    2.Service类中的onBind方法将downloadBinder暴露给客户端
    3.客户端MainActivity中在onServiceConnected中接受服务端的downloadBinder并使用其中的方法
    4.使用bindService(intent,connection,BIND_AUTO_CREATE)开启服务
    5.解绑服务使用unbindService(connection)

    3.服务的生命周期

    服务的生命周期

    3.1 服务的启动方式对比

    如上述所说,服务的启动方式有两中,一种是startService,一种是bindService
    这两种启动服务的方式具体有什么不同?

    第一种是通过startservice方式来启动,通过此方式来启动的service会一直运行在后台,除非调用者主动停止服务或者是系统异常杀死。 此过程对应的生命周期是:onCreate()----onStartCommand()-----onStop()----onDestory()

    • 只会创建一个Service实例,onCreate只会执行一次,onStartCommand在每次startService的时候执行
    • 适用于简单的服务启动

    第二种是通过bindService方式来启动,通过此方式来启动的service会和调用者的生命周期绑定,调用者被销毁的时候,service也会被销毁, 此过程对应的生命周期是:onCreate()----onBind()-----onUnbind()----onStop()----onDestory()

    • 当我们使用同一个contextserviceconnection去执行bindservice时,onServiceConnected方法只会被回调一次
    • 直接finish(),不会调用unbindService方法,Service在Activity销毁后,自行解除绑定然后销毁。
    • 适用于需要活动和Service数据交互的场景

    4.IntentService

    • Service运行在主线程,因此不能处理大量耗时的操作,于是可以尝试开启线程
    • Service中开启线程和运行完后停止服务这两个操作经常容易忘记

    因此,Android提供了IntentService。它需要实现onHandleIntent()onDestroy()两个函数

    参考资料:
    Android开发中的Service的两种启动方式的坑

    相关文章

      网友评论

        本文标题:第一行代码(3)服务

        本文链接:https://www.haomeiwen.com/subject/goklnctx.html