Android四大组件——Service

Service的生命周期与启动/停止服务

timg.jpg
public class MyService extends Service {
    private final static String TAG = "MyService";

    public MyService() {
    }
    
    //服务被创建时调用
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    //服务被启动时调用
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    //服务被销毁时调用
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_service:
                Intent startIntent = new Intent(this, MyService.class);
                //启动服务
                startService(startIntent);
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this, MyService.class);
                //停止服务
                stopService(stopIntent);
                break;
            default:
                break;
        }
    }

启动服务后的日志为

图片.png

当再次点击启动服务按钮时,日志为

图片.png

可以看出onCreate()方法不再执行,即onCreate()方法只会在服务第一次被创建的时候执行。
点击停止服务的按钮时,日志为

图片.png

即onDestory()方法被执行

在Service中调用stopSelf()方法也可以停止服务


Activity与Service通信

Service代码

    //Activity与Service通信时使用
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return mBinder;
    }

    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {
        public void startDownload() {
            Log.d(TAG, "startDownload");
        }

        public int getProcess() {
            Log.d(TAG, "getProcess");
            return 0;
        }
    }

Activity代码

    private MyService.DownloadBinder downloadBinder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        //Activity与Service绑定成功时调用
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            //向下转型得到DownloadBinder实例,该实例可以调用DownloadBinder的public方法
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProcess();
        }

        //Activity与Service解除绑定时调用
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };
            case R.id.bind_service:
                Intent bindIntent = new Intent(this, MyService.class);
                /**
                 * 绑定服务,第一个参数为Intent对象,
                 * 第二个参数为ServiceConnection对象
                 * 第三个参数为flag标识,BIND_AUTO_CREATE表示自动创建service,
                 * 此时onCreate()方法执行,onStartCommand()方法不会执行
                 */
                bindService(bindIntent, connection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind_service:
                //解除绑定
                unbindService(connection);
            default:
                break;

日志打印结果为

图片.png

即绑定服务时onBind()方法会被调用,且通过其返回一个Binder对象给Activity,从而在Activity中通过对象转型来调用Service中的方法

点击解除绑定按钮日志输出为

图片.png

当执行startService()后执行bindService()方法,此时要销毁服务需要同时调用stopService()方法和unbindService()方法后,onDestory()方法才会被调用

启动服务

图片.png

绑定服务

图片.png

停止服务和解除绑定服务

图片.png

Service的扩展知识

使用前台服务

前台服务的特征:有一个运行图标一直在系统的状态栏显示

    //服务被创建时调用
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
        Intent intent=new Intent(this,MainActivity.class);
        /**
         * 第一个参数为上下文对象
         * 第二个参数为requestCode返回码
         * 第三个参数为Intent对象
         * 第四个参数为flags标识
         */
        PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);
        Notification notification=new NotificationCompat.Builder(this)
                .setContentTitle("This is content title")
                .setContentText("This is content text")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.mipmap.ic_launcher))
                .setContentIntent(pendingIntent)
                .build();
        //启动前台服务,第一个参数为通知的id
        startForeground(1,notification);
    }
GIF.gif

服务的特征

服务是运行在主线程中的,耗时操作会造成ANR
在Service与Activity中分别加入以下代码打印线程id

        Log.d("MyService", "MainActivity thread id is " + Thread.currentThread().getId());
        Log.d("MyService", "Service thread id is " + Thread.currentThread().getId());
图片.png

由Log打印日志可知Service与Activity确实运行在同一线程中,因此不能在Service中进行耗时操作,正确的使用方法是在每个服务中去开启一个子线程,在子线程中进行耗时操作,写法可以为

    //服务被启动时调用
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        new Thread(new Runnable() {
            @Override
            public void run() {
                //在子线程中处理耗时操作
                stopSelf();
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

开发中可能出现忘记开启线程或调用stopSelf()方法结束服务,所以可以使用IntentService类来创建一个异步且会自动停止的服务。
IntentService类

public class MyIntentService extends IntentService {

    //该无参构造方法必须实现,且格式固定,需要调用父类的有参构造函数来实例化Service
    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //根据intent的不同来处理不同的逻辑
        Log.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());
        String value = intent.getStringExtra("test");
        Log.d("MyIntentService", "intentService2 " + value);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyIntentService", "onDestroy");
    }
}

MainActivity

            case R.id.start_intent_service:
                //启动IntentService服务
                Log.d("MyIntentService", "Activity thread id is " + Thread.currentThread().getId());
                Intent intentService = new Intent(this, MyIntentService.class);
                Intent intentService2 = new Intent(this, MyIntentService.class);
                intentService2.putExtra("test", "executed");
                startService(intentService);
                startService(intentService2);
                break;
图片.png

由日志可以看出IntentService与Activity没有运行在同一线程中,且onHandleIntent()方法会先后处理不同的intent,只有处理完所有的intent请求后onDestory()方法才会执行,以此自动停止服务。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容