【第一行代码学习笔记】四大组件之Service

服务

服务简介

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

服务并不是在一个独立进程中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉,所有依赖于该应用程序的服务也会停止服务。

我们需要在服务内部手动创建子进程,并在这里执行具体的服务,否则有可能出现主进程被阻塞的情况。

异步消息处理机制

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int UPDATE_TEXT = 1;
    private TextView mText;

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            //主线程中运行
            switch (msg.what){
                case UPDATE_TEXT:
                    mText.setText("Nice to meet you!");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mText = this.findViewById(R.id.text);
        Button button = this.findViewById(R.id.change_text);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {

        switch (view.getId()){
            case R.id.change_text:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = UPDATE_TEXT;
                        mHandler.sendMessage(message);
                    }
                }).start();
                break;
        }
    }
}

1.在主线程中创建一个Handler对象,并重写handlerMessage()方法

2.当子线程需要进行UI操作,就创建一个Message对象,并通过Handler将这条消息发出去

3.之后这条消息会被加入MessageQueue中等待被处理

4.而Looper会一直试图从MessageQueue中取出待处理消息,最后会分发回到Handler中的handlerMessage()中。

在这里插入图片描述

服务的基本用法

定义一个服务
public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    /**
     * 服务创建时调用
     */
    @Override
    public void onCreate() {
        super.onCreate();
    }

    /**
     * 服务启动时调用
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);

    }

    /**
     * 服务销毁时调用
     */
    @Override
    public void onDestroy() {
        super.onDestroy();

    }
}
启动和停止服务

1.活动决定何时开启或停止服务

Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);//启动服务——活动决定服务的开启

Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);//停止服务——活动决定服务停止

2.服务自己停止:在服务中任意位置调用stopSelf()

活动和服务进行通信
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private MyService.DownloadBinder mDownloadBinder;

    private ServiceConnection mConnection = new ServiceConnection() {

        /**
         * 活动与服务绑定成功时调用
         * @param componentName
         * @param iBinder 在这里可以向下转型得到mDownloadBinder实例
         *                然后调用DownloadBinder中的方法实现活动指挥服务
         */
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d(TAG, "onServiceConnected...");
            mDownloadBinder = (MyService.DownloadBinder) iBinder;
            mDownloadBinder.startDownload();
            mDownloadBinder.getProcess();
        }

        /**
         * 活动与服务解绑时调用
         * @param componentName
         */
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected...");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
    }

    @Override
    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;
            case R.id.bind_service:
                Intent bindIntent = new Intent(this, MyService.class);
                bindService(bindIntent, mConnection, BIND_AUTO_CREATE);
                //BIND_AUTO_CREATE表示在活动和服务进行绑定后自动创建服务(如果没床架)
                //但是绑定成功时候会先调用 ServiceConnection.onServiceConnected()
                break;
            case R.id.unbind_service:
                unbindService(mConnection);
                break;
            default:
                break;
        }
    }
}

服务的生命周期

1.一旦在项目的任何地方调用了Context的startService()方法,相应的服务就会被启动起来

  • 如果这个服务没有创建过,就会先调用onCreate(),然后调用onStartCommand();如果这个服务被创建过,就直接回调onStartCommand()
  • 即,每调用一次startService()就会调用一次onStartCommand()

2.服务启动会就会一直保持运行状态,直到Context的stopService()或者Service的stopSelf()被调用

  • 一个服务只有一个实例,所以可以startService()很多次,但关闭只需要一次stopService()或者stopSelf()
  • 调用stopService()之后,服务中的onDestroy就会执行

3.调用Context的bindService()方法,就会获得服务的持久连接

  • 如果bindService()第三个参数是BIND_AUTO_CREATE
    • 如果Service没创建,就会自动创建,会调用onCreate()和onBind(),但不会调用onStartCommand(),即onCreate() -> onBind() -> ServiceConnection.onServiceConnected()
    • 如果Service创建了,就直接调用onBind(),即onBind() -> ServiceConnection.onServiceConnected()

4.调用Context的unbindService()方法,就会获得解绑

  • 调用unbindService()之后,服务中的onDestroy就会执行
  • 同时调用StartService和bindService()关闭时需要unbindService()和stopService()

在这里插入图片描述

前台服务

前台服务和普通服务的区别在于:

  • 前台服务会有一个正在运行的图标在系统的状态栏,下拉可查看详细信息,效果类似于通知;‍
  • 普通服务在系统内存不足时可能会被回收,而前台服务不会;‍
public class MyService extends Service {
    ...
    
    /**
     * 服务创建时调用
     */
    @Override
    public void onCreate() {
        super.onCreate();
        
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("my_service", "前台service通知", NotificationManager.IMPORTANCE_DEFAULT);
            manager.createNotificationChannel(channel);
        }
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        Notification notification = new NotificationCompat.Builder(this, "my_service")
                .setContentTitle("This is content titele")
                .setContentText("This is content text")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        startForeground(1, notification);//调用该方法后会让MyService变成一个前台服务,并在系统状态栏显示出来
    }
}
IntentService:集开启线程和自动停止线程于一身
//记得要注册一下
public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService");
    }
    /**
     * 这个方法是在子线程中运行的
     * 这里可用于处理一些具体逻辑,不会发生ANR(Application not responding)的问题
     * @param intent
     */
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.d("MyIntentService", "onHandleIntent: Thread id is " + Thread.currentThread().getId());
    }
    /**
     * onHandleIntent调用结束即具体逻辑处理完后,会自动调用onDestroy, 停止该服务的
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyIntentService", "onDestroy...");
    }
}
//IntentService启动,与一般的Service启动无疑
Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值