Android基础 ---- 四大组件之Services

一、进程

  • 什么是进程?
    一个程序就是一个进程。比如QQ、微信、微博等,其中每个程序都叫做一个进程
  • Android系统下进程的特点
    The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes.
    翻译:Android系统应该尽可能长的去维护一个应用程序进程,但是在实际情况下,通常我们需要为了新进程或者更重要的进程得到内存而去删除旧进程。
    根据API,那么什么时候删除旧进程呢?这里我们就需要知道进程的优先级
  • 进程的优先级(由高到低)
    • Foreground process(前台进程)
      • 优先级最高的进程。相当于activity执行了 onResume() 方法,用户正在交互
    • Visible process(可视进程)
      • 优先级较高。相当于activity执行了 onPause() 方法,界面可见但不可交互
    • Service process(服务进程)
      • 优先级高。调用了 startService() 方法后,就会开启一个服务进程
    • Background process(后台进程)
      • 优先级低。相当于activity执行了 onStop() 方法,界面不可见(按手机上面的Home键时,进程就会成为后台进程)
    • Empty process(空进程)
      • 优先级最低。界面不可见,并且activity被销毁(一直按手机上面的返回键,直到退出程序时,进程就会成为空进程),不会维持任何组件运行。当进程类型变成这种时,系统并不会马上就杀死进程,它存活的原因只有一个,就是保存缓存数据,让下一次打开这个应用的时候比第一次打开这个应用程序速度快一些。
  • 一般杀进程的时候最多杀到 Background process,就不会再继续杀下去了


二、服务

  • 什么是服务?
    服务是在后台运行的,是没有界面的activity

  • 如何创建一个服务(四大组件的创建方式都是一样的)?

    • 创建一个类去继承Service
      package com.example.chenzhaoyu.serverdemo;
      
      import android.app.Service;
      import android.content.Intent;
      import android.os.IBinder;
      
      public class DemoService extends Service {
          // 服务第一次创建时调用
          @Override
          public void onCreate() {
              super.onCreate();
          }
      
          // 服务在开启的时候就会调用(开启包括第一次创建服务的时候)
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
              return super.onStartCommand(intent, flags, startId);
          }
      
          // 当其他组件绑定该服务时调用
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
      
          // 服务在销毁时调用
          @Override
          public void onDestroy() {
              super.onDestroy();
          }
      }
      
    • 在 AndroidManifest.xml 中去配置一个服务
      <application
              android:allowBackup="true"
              android:icon="@mipmap/ic_launcher"
              android:label="@string/app_name"
              android:roundIcon="@mipmap/ic_launcher_round"
              android:supportsRtl="true"
              android:theme="@style/AppTheme">
              <activity android:name=".MainActivity">
                  <intent-filter>
                      <action android:name="android.intent.action.MAIN" />
                      <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
              </activity>
              <service android:name=".DemoService" />
      </application>
      
  • 如何使用一个服务(两种方式)?

    • 通过 startService() 与 stopService(Intent intent) 方式
      • 通过调用 startService(Intent intent) 方法,可以开启一个服务(开启一个服务与开启一个activity的方式一样)
      • 通过调用 stopService(Intent intent) 方法,可以关闭一个服务
        package com.example.chenzhaoyu.serverdemo;
        
        import android.content.Intent;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.view.View;
        
        public class MainActivity extends AppCompatActivity {
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
            }
        
            // 开启一个服务
            public void click1(View view) {
               Intent intent = new Intent(this,DemoService.class);
               startService(intent);
            }
            
         	 // 关闭一个服务
        	public void click2(View view) {
        		 Intent intent = new Intent(this,DemoService.class);
        		 stopService(intent);
        	}
        }
        
    • 通过 bindService() 与 unbindService()方式
      • 通过 bindService(Intent service, ServiceConnection conn,
        int flags) 可以绑定一个服务(即开启一个服务)
      • 通过 unbindService(ServiceConnection conn) 可以解绑一个服务(即关闭一个服务)
        package com.example.chenzhaoyu.serverdemo;
        
        import android.content.ComponentName;
        import android.content.Intent;
        import android.content.ServiceConnection;
        import android.os.IBinder;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.View;
        
        public class MainActivity extends AppCompatActivity {
        
            private MyServiceConn conn;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
            }
        
            // 开启一个服务
            public void click1(View view) {
                /*
                 *      参数一:Intent类型,明确需要绑定的服务
                 *      参数二:ServiceConnection类型,用于检测服务的状态
                 *      参数三:int类型,用于设置绑定的操作选项
                 * */
                conn = new MyServiceConn();
                Intent intent = new Intent(this,DemoService.class);
                bindService(intent,conn,BIND_AUTO_CREATE);
            }
        
            class MyServiceConn implements ServiceConnection{
        
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.i("aaa","绑定成功");
                }
        
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.i("aaa","绑定失败");
                }
            }
        
            // 关闭一个服务
            public void click2(View view) {
                unbindService(conn);
            }
        
            @Override
            protected void onDestroy() {
                unbindService(conn);
                super.onDestroy();
            }
        }
        
  • 开启服务的特点:

    • 通过 startService(Intent intent) 开启一个服务的特点:
      • 第一次开启服务的时候会调用 onCreate() 和 onStartCommand(Intent intent, int flags, int startId) 方法
      • 当服务已经开启后,再一次开启服务时只会调用 onStartCommand(Intent intent, int flags, int startId) 方法
      • 服务一旦被开启,服务就会在后台长期运行,直到用户手动停止
      • 通过 startService(Intent intent) 开启一个服务,服务可以在设置页面找到
    • 通过 bindService() 开启一个服务的特点:
      • 第一次开启服务的时候会调用 onCreate() 和 onBind(Intent intent) 方法
      • 当服务开启后,再一次开启服务时不会再调用任何方法
      • 当onBind(Intent intent) 方法的返回值为 null 时,onServiceConnected(ComponentName name, IBinder service) 方法不会执行
      • Activity一旦调用了 onDestroy() 方法,服务就会自动停止
      • 服务不可以多次解绑,多次解绑会报异常
      • 通过 bindService() 开启一个服务,服务不可以在设置页面找到


三、bindService() 方法

  • 已经有了 startService() 方法,为什么还要引入 bindService() 方法?
    • 目的是为了调用服务里面的方法
  • 如何调用服务里面的方法呢
    • 方法一(适用于内部类中的方法希望全部对调用者公开时):
      • 创建一个类继承 Service 类
      • 在 AndroidManifest.xml 文件中配置服务
      • 在服务里面创建一个方法
      • 创建一个类继承 IBinder 的子类 Binder
      • 在这个类中创建一个方法,去调用服务中的方法
      • 在 onBind() 中将内部类对象返回
      • 在Activity中,通过 bindService() 开启服务
      • 在 onServiceConnected() 方法中将服务中的内部类对象取出
      • 通过取出的对象调用内部类中的方法
      • 当Activity销毁时,关闭服务
        // 服务端代码
        package com.example.chenzhaoyu.serverdemo;
        
        import android.app.Service;
        import android.content.Intent;
        import android.os.Binder;
        import android.os.IBinder;
        import android.widget.Toast;
        
        public class TestService extends Service {
            // 当Activity开启一个服务时,会调用这个方法,我们将内部类对象返回
            @Override
            public IBinder onBind(Intent intent) {
                IBinder ib = new MyBinder();
                return ib;
            }
        
            public void method(){
                Toast.makeText(this,"TestService",Toast.LENGTH_LONG).show();
            }
        
            // 定义中间人 用于调用服务中的方法
            class MyBinder extends Binder {
                public void getMethod(){
                    method();
                }
            }
        }
        
        // Java端代码
        package com.example.chenzhaoyu.serverdemo;
        
        import android.content.ComponentName;
        import android.content.Intent;
        import android.content.ServiceConnection;
        import android.os.IBinder;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.view.View;
        
        public class MainActivity extends AppCompatActivity {
        
            private TestService.MyBinder binder;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                
                // 开启服务器
                Intent intent = new Intent(this,TestService.class);
                MyServiceConn conn = new MyServiceConn();
                bindService(intent, conn, BIND_AUTO_CREATE);
            }
        
            public void click1(View view) {
                // 通过内部类中的方法去间接调用服务中的方法
                binder.getMethod();
            }
            
            class MyServiceConn implements ServiceConnection {
        
                // 当onBind()方法返回不为null时,会调用这个方法,我们可以在这个方法中将服务中的内部类对象取出
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    binder = (TestService.MyBinder) service;
                }
        
                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
            }
            
            // 当Activity销毁时关闭服务
            @Override
            protected void onDestroy() {
                unbindService(conn);
                super.onDestroy();
            }
        }
        
    • 方法二(适用于内部类中的方法希望部分对调用者公开时):
      • 创建一个类继承 Service 类
      • 在 AndroidManifest.xml 文件中配置服务
      • 在服务里面创建几个方法
      • 创建一个私有类继承 IBinder 的子类 Binder
      • 在这个类中创建几个方法,去调用服务中的方法
      • 创建一个接口,将自定义的私有类中需要暴露给调用者的方法写在接口中
      • 在 onBind() 中将内部类对象返回
      • 在Activity中,通过 bindService() 开启服务
      • 在 onServiceConnected() 方法中将服务中的内部类对象取出,此时类型为前面创建的接口类型
      • 通过取出的对象调用内部类中的方法
      • 当Activity销毁时,关闭服务
        // 服务端实现
        package com.example.chenzhaoyu.serverdemo;
        
        import android.app.Service;
        import android.content.Intent;
        import android.os.Binder;
        import android.os.IBinder;
        import android.widget.Toast;
        
        public class TestService extends Service {
            // 当Activity开启一个服务时,会调用这个方法,我们将内部类对象返回
            @Override
            public IBinder onBind(Intent intent) {
                IBinder ib = new MyBinder();
                return ib;
            }
        
            public void method(){
                Toast.makeText(this,"TestService",Toast.LENGTH_LONG).show();
            }
        
            public void readBook(){
                Toast.makeText(this,"读书",Toast.LENGTH_LONG).show();
            }
        
            // 定义中间人 用于调用服务中的方法
            private class MyBinder extends Binder implements IsService{
                public void getMethod(){
                    method();
                }
        
                @Override
                public void getReadBook() {
                    readBook();
                }
            }
        }
        
        // 接口端实现
        package com.example.chenzhaoyu.serverdemo;
        
        public interface IsService {
            void getReadBook();
        }
        
        // Java端实现
        package com.example.chenzhaoyu.serverdemo;
        
        import android.content.ComponentName;
        import android.content.Intent;
        import android.content.ServiceConnection;
        import android.os.IBinder;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.view.View;
        
        public class MainActivity extends AppCompatActivity {
        
            private IsService binder;
            private Intent intent;
            private MyServiceConn conn;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                intent = new Intent(this,TestService.class);
                conn = new MyServiceConn();
                bindService(intent, conn, BIND_AUTO_CREATE);
            }
        
            public void click1(View view) {
                // 通过内部类中的方法去间接调用服务中的方法
                binder.getReadBook();
            }
            class MyServiceConn implements ServiceConnection {
        
                // 当onBind()方法返回不为null时,会调用这个方法,我们可以在这个方法中将服务中的内部类对象取出
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    // 因为内部类已经私有化,不能访问,因此取出的类型只能为接口类型
                    binder = (IsService) service;
                }
        
                @Override
                public void onServiceDisconnected(ComponentName name) {
        
                }
            }
        
            // 当Activity销毁时关闭服务
            @Override
            protected void onDestroy() {
                unbindService(conn);
                super.onDestroy();
            }
        }
        



四、如何使用混合方式开启服务?

  • 流程
    • 先使用 startService() 方法开启服务
    • 再使用 bindService() 获取服务中的方法
    • 再使用 unbindService() 解绑服务
    • 最后使用stopService() 方法解绑服务
  • 案例(利用混合方式开启音乐盒):
    // 服务端实现
    package com.example.chenzhaoyu.serverdemo;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.widget.Toast;
    
    public class MusicService extends Service {
        @Override
        public IBinder onBind(Intent intent) {
            return new MyBinder();
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
        private class MyBinder extends Binder implements IService{
    
            @Override
            public void playMusic() {
                Toast.makeText(getApplicationContext(),"播放音乐",Toast.LENGTH_LONG).show();
            }
    
            @Override
            public void replayMusic() {
                Toast.makeText(getApplicationContext(),"重新播放音乐",Toast.LENGTH_LONG).show();
            }
    
            @Override
            public void pauseMusic() {
                Toast.makeText(getApplicationContext(),"暂停播放音乐",Toast.LENGTH_LONG).show();
            }
        }
    }
    
    // 接口端实现
    package com.example.chenzhaoyu.serverdemo;
    
    public interface IService {
        void playMusic();
        void replayMusic();
        void pauseMusic();
    }
    
    // Java端实现
    package com.example.chenzhaoyu.serverdemo;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        private IService sv;
        private MyServiceConn conn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Intent intent = new Intent(this,MusicService.class);
            startService(intent);
            conn = new MyServiceConn();
            bindService(intent, conn,BIND_AUTO_CREATE);
        }
    
        public void click1(View view) {
            sv.playMusic();
        }
    
        public void click2(View view) {
            sv.pauseMusic();
        }
    
        public void click3(View view) {
            sv.replayMusic();
        }
    
        class MyServiceConn implements ServiceConnection{
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                sv = (IService) service;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 目的是为了不报错
            unbindService(conn);
        }
    }
    



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值