• Android学习笔记---Service及IntentService理解


    Android学习笔记---Service及IntentService理解

    一.Android Service服务:

          Android中的服务是运行在后台的服务,他是不可见的没有界面的东西。你可以启动一个服务Service来播放音乐,或者记录你地理信息位置的改变,或者启动一个服务来运行并一直监听某种动作。Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。你可以在服务中开一一个线程,在线程中做耗时动作。

    服务的生命周期图:

     

     

    1.如何创建和开启一个服务:

    第一步:创建一个类 ExampleService.java 继承android.app.Service

    第二步:覆盖其中继承的方法 如下:

     

    public class ExampleService extends Service
    {
    
        private static final String TAG = "Example";
    
        @Override
        public IBinder onBind(Intent intent)
        {
            return null;
        }
    
        @Override
        public void onCreate()
        {
            Log.i(TAG, "ExampleService===>>onCreate");
            super.onCreate();
        }
    
        @Override
        public void onStart(Intent intent, int startId)
        {
            Log.i(TAG, "ExampleService===>>onStart");
    
            super.onStart(intent, startId);
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
            Log.i(TAG, "ExampleService===>>onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public void onDestroy()
        {
            Log.i(TAG, "ExampleService===>>onDestroy");
            super.onDestroy();
        }
    
    }

     

    第三步:启动服务:

        Intent intent = new Intent(MainActivity.this, ExampleService.class);
        startService(intent);

    第四步:关闭服务:

    stopService(intent);//关闭服务

    服务运行的生命周期顺序:

    [onCreate()-->onStartCommand()--->onStart()-->运行服务--->调用stopService()--->onDestory()]

    在Activity中通过startService()开启的服务,开启之后及时现在我们关闭Activity服务还一直在后台运行,只有调用stopService()才能关闭服务。

    关闭Activity之后 我们在此点击按钮 重新开启服务。

    注意:服务在后台运行我们再次点击startService()开启服务。将不会在调用 onCreate()服务。一个服务只会创建一次,销毁一次,但可以开始多次,因此,onCreate和onDestroy方法只会被调用一次,而onStart(或onStartCommand)方法会被调用多次。

    如下图:

     

    点击stopService()方法将关闭服务:

     

     注意:onStart方法是在Android2.0之前的平台使用的.在2.0及其之后,则需重写onStartCommand方法,同时,旧的onStart方法则不会再被调用.    

     

     

    二.bindService()

     

          Bound service 允许其它的组件(比如Activities)绑定到这个Service上,可以发送请求,也可以接受请求,甚至进行进程间的通话。Bound service 仅仅在服务于其它组件时存在,不能独自无限期的在后台运行。

     

     

         调用者和服务绑在一起,调用者一旦退出服务也就终止[onCreate()-->onBind()-->onUnbind()-->onDestory()]

    1.创建Bound Services

         当创建一个能提供绑定功能的服务时,我们必须提供一个IBinder对象,客户端能使用这个对象与服务进行交互。在Android中有三种方式定义方式:

             1.扩展Binder类

             2.使用Messenger

             3.使用AIDL (Android Interface Definition Language)

       创建 步骤:

          第一步:.创建一个类BinderService.java 继承 android.app.Service

    public class BinderService extends Service
    {
    
        public class MyBinder extends Binder
        {
            public BinderService getBinderService()
            {
                return BinderService.this;
            }
        }
        private MyBinder binder=new MyBinder();
        private static final String TAg = "BinderService";
        @Override
        public IBinder onBind(Intent intent)
        {
            Log.i(TAg, "BinderService===>onBind()");
            return binder;
        }
        public void UpFile()
        {
            Log.i(TAg, "BinderService===>UpFile()");
        }
        @Override
        public void onCreate()
        {
            Log.i(TAg, "BinderService===>onCreate()");
            super.onCreate();
        }
        @Override
        public void onDestroy()
        {
            Log.i(TAg, "BinderService===>onDestroy()");
            super.onDestroy();
        }
        @Override
        public boolean onUnbind(Intent intent)
        {
            Log.i(TAg, "BinderService===>onUnbind()");
            return super.onUnbind(intent);
        }
        
    
    }

    第二步:在Service类中,创建一个Binder实例 包含客户端能调用的公共方法 返回当前服务对象

      

    public class MyBinder extends Binder
        {
            public BinderService getBinderService()
            {
                return BinderService.this;
            }
        }

    第三步:在onBind()方法中返回Binder实例

        private MyBinder binder=new MyBinder();
        private static final String TAg = "BinderService";
        @Override
        public IBinder onBind(Intent intent)
        {
            return binder;
        }

    第四步:在客户端,从onServiceConnected()方法中获得Binder实例。

    private void bindService()
        {
            Intent intent=new Intent(MainActivity.this,BinderService.class);
            bindService(intent,conn,Context.BIND_AUTO_CREATE);
        } 
       private void unBind()
       {
           if(isConnected)
           {
               unbindService(conn);
           }
       }
        private ServiceConnection conn=new ServiceConnection()
        {
            @Override
            public void onServiceDisconnected(ComponentName name)
            {
               isConnected=false;
                
            }
            @Override//在onServiceConnected 中获取Binder的实例
            public void onServiceConnected(ComponentName name, IBinder binder)
            {
                MyBinder myBinder=(MyBinder)binder;
                BinderService service=myBinder.getBinderService();
                service.UpFile();
                isConnected=true;
            }
        };

    通过调用 bindService()开启服务 。

    调用unBind()关闭服务,或者我们关闭Activity也会关闭服务

    三.Android中Service运行在主线程中。

        Android 中的服务是运行在主线程上的,通过下面的例子来说明Android服务运行的线程。如果是运行在主线程的,

    那在服务中步要运行太耗时的操作。如果运行态耗时的操作将会是整个Activity处于假死状态,无在进行别的操作。如何要运行耗时操作

    要用到多线程Thread 或者异步操作 InentService.

    创建一个 MyServiceThread.java 继承 Service的服务:

    public class MyServiceThread extends Service
    {
    
        private static final String TAG = "MyServiceThread";
    
        @Override
        public IBinder onBind(Intent intent)
        {
            return null;
        }
    
        @Override
        public void onCreate()
        {
            Log.i(TAG, "MyServiceThread===>>onCreatre===>>线程ID:"+Thread.currentThread().getId());
            super.onCreate();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
        
            try
            {
    //这里进行耗时的操作 Log.i(TAG,
    "MyServiceThread===>>onStartCommand===>>线程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下载。。。。。"); Thread.sleep(5000); Log.i(TAG, "文件下载完成。"); } catch (InterruptedException e) { e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "MyServiceThread===>>onDestroy===>>线程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }

    程序为开启耗时服务时:

        开启耗时服务时:

    运行截图:下图可看出Android 中的Service确实是运行在主线程中。从运行前和运行后,当我们点击开启服务,按钮在服务没有运行

    结束时,背景处于黄色,此时不能进行其他的操作。如果要运行耗时的操作需要应用多线程操作。

    三.Android中Service多线程操作运行耗时操作。

        一下演示Android服务如何在多线程下进行耗时操作。

    1.创建ManyThreadService.java 服务

    public class ManyThreadService extends Service
    {
    
        private static final String TAG = "ManyThreadService";
    
        @Override
        public IBinder onBind(Intent intent)
        {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void onCreate()
        {    
            Log.i(TAG, "ManyThreadService==>>onCreate==>线程ID:"+Thread.currentThread().getId());
        
        }
        private class MyThread extends Thread
        {
    
            @Override
            public void run()
            {
                
                try
                {
                    Log.i(TAG, "ManyThreadService==>>文件下载线程ID:"+Thread.currentThread().getId());
                    Log.i(TAG, "文件下载中。。。。。>>文件现在线程ID:"+Thread.currentThread().getId());
                    Thread.sleep(5000);
                    Log.i(TAG, "文件现在完成。 >>文件下线线程ID:"+Thread.currentThread().getId());
                } catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
            
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
            
            Log.i(TAG, "ManyThreadService==>>onStartCommand中开启线程==>线程ID"+Thread.currentThread().getId());
            new MyThread().start();
            return START_STICKY;
        }
        @Override
        public void onDestroy()
        {
            Log.i(TAG, "ManyThreadService==>>onDestory==>线程ID"+Thread.currentThread().getId());
            super.onDestroy();
        }
        
    
    }

    2.创建新线程进行耗时操作:

    private class MyThread extends Thread
        {
    
            @Override
            public void run()
            {
                
                try
                {
                    Log.i(TAG, "ManyThreadService==>>文件下载线程ID:"+Thread.currentThread().getId());
                    Log.i(TAG, "文件下载中。。。。。>>文件现在线程ID:"+Thread.currentThread().getId());
                    Thread.sleep(5000);
                    Log.i(TAG, "文件现在完成。 >>文件下线线程ID:"+Thread.currentThread().getId());
                } catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
            
        }

    3.开启新线程:

    public int onStartCommand(Intent intent, int flags, int startId)
        {
            
            Log.i(TAG, "ManyThreadService==>>onStartCommand中开启线程==>线程ID"+Thread.currentThread().getId());
            new MyThread().start();
            return START_STICKY;
        }

    运行效果:从下图看出出,多线程并行操作,提高执行的效率。如果要在Android服务中执行耗时的并行操作服务,适应多线程操作时不错的选择。

    如果只是运行异步请求操作 IntentService是不错的选择。

    三.Android中IntentSevice操作。

          IntentService是Service类的子类,用来处理异步请求。客户端通过startService(Intent)方法传递请求给IntentService,

     IntentService通过worker thread处理每个Intent对象,执行完所有工作后自动停止Service。

     写构造方法 复写onHandleIntent()方法

    IntentService执行如下操作 

       1.创建一个与应用程序主线程分开worker thread用来处理所有通过传递过来的Intent请求

       2.创建一个work queue,一次只传递一个intent到onHandleIntent()方法中,从而不用担心多线程带来的问题

       3.当处理完所有请求后自动停止服务,而不需要我们自己调用stopSelf()方法

       4.默认实现了onBind()方法,返回值为null

       5. 默认实现了onStartCommand()方法,这个方法将会把我们的intent放到work queue中,然后在onHandleIntent()中执行。

    创建 MyIntentService.java 继承:android.app.IntentService

    public class MyIntentService extends IntentService
    {
    
        private static final String TAG = "MyIntentService";
        public MyIntentService()
        {
            super("MyIntentService");
        }
        @Override
        public IBinder onBind(Intent intent)
        {
            return null;
        }
        @Override
        public void onCreate()
        {
             Log.i(TAG, "MyIntentService==>>onCreate==>>线程ID:"+Thread.currentThread().getId());
            super.onCreate();
        }
        
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
             Log.i(TAG, "MyIntentService==>>onStartCommand==>>线程ID:"+Thread.currentThread().getId());
            return super.onStartCommand(intent, flags, startId);
        }
        @Override
        protected void onHandleIntent(Intent intent)
        {
            
            try
            {
                Log.i(TAG, "MyIntentService==>>onHandleIntent==>>线程ID:"+Thread.currentThread().getId());
                Log.i(TAG, "文件下载中。。。。。>>文件下载线程ID:"+Thread.currentThread().getId());
                Thread.sleep(5000);
                Log.i(TAG, "文件现在完成>>文件下载线程ID:"+Thread.currentThread().getId());
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
    
        }
        @Override
        public void onDestroy()
        {
             Log.i(TAG, "MyIntentService==>>onDestory==>>线程ID:"+Thread.currentThread().getId());
            super.onDestroy();
        }
    
    }

    运行效果:从下图可以看出,在每次开启服务时传过去的inent,耗时操作都是有一个线程来执行处理。而所有操作排列成一个线程队列,先执行完个操作,紧接着

    执行下一个操作。执行完所以操作后 服务会自动onDestory操作进行销毁。

    本写的这里,有些问题是我通过实验总结出来的,有错误的地方请指出来。错误的地方希望大家指出。谢谢。

     

  • 相关阅读:
    Java读书笔记
    b_aw_旅游计划(树的中心变形)
    b_lc_秋叶收集器(分类讨论dp+滚动数组优化)
    b_lg_涂色(从小区间做起,讨论s[l]和s[r]的关系)
    c_lc_早餐组合(排序+双指针)
    c_aw_鱼塘钓鱼(大根堆)
    b_pat_栈(2*multiset+stack)
    c_pat_推荐系统(set模拟)
    b_lg_时态同步(后序遍历统计每棵子树的最大高度)
    b_lc_统计不开心的朋友(预处理+模拟)
  • 原文地址:https://www.cnblogs.com/xieyong_198510/p/3479408.html
Copyright © 2020-2023  润新知