Service

  • 服务的作用?

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

  • 服务与应用进程的关系

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

服务的生命周期

  • onCreate()
  • onStartCommand()
  • onDestory()

    如何调用服务

    Context.startService()
    1. <service android:name=".service.MyService"/>
    同时需要在Manifest中进行注册:

如何停止服务?

stopService() 或stopSelf()

补充: 如何开启新的线程?

  1. new Thread(){
  2. @Override
  3. public void run(){
  4. //耗时的操作
  5. }
  6. }.start();

简便的service服务:IntentService

IntentService将用户的请求执行在一个子线程中,用户只需要覆写onHandleIntent函数,并且在该函数中完成自己的耗时操作即可。需要注意的是,在任务执行完毕之后IntentService会调用stopSelf自我销毁,因此,它适用于完成一些短期的耗时任务。

  1. public class MyIntentService extends IntentService{
  2. MyIntentService(){
  3. super(MyIntentService.class.getname());
  4. }
  5. @override
  6. protected void onHandleIntent(Intent intent)
  7. {
  8. //耗时的操作
  9. }
  10. }

线程

定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时逻辑即可

异步消息处理机制:
由四部分组成:

  • Message:线程之间传递的消息。
  • Handler:处理者。有sendMessage()和handleMessage()两个方法。
  • MessageQuene:消息队列,用于存放所有的消息,每一个线程中只有一个messageQuene对象
  • Looper: MessageQuene中的管家,当我们调用Loop()方法后,就会进入无限循环,

不过为了更加方便我们在子线程中对UI进行操作,Android还提供了另外一些好用的工具,比如AsyncTask。借助AsyncTask,即使你对异步消息处理机制完全不了解,也可以十分简单地从子线程切换到主线程。

AsyncTask

安卓中封装好的异步消息处理机制
有3个参数:

  • Params:执行asyncTask需要传入的参数
  • Progress:后台执行任务时,在界面上显示当前的进度
  • Result:返回结果

有哪4个方法需要重写:

  • onPreExecute():这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等
  • doInBackground()
  • onProgressUpdate()
  • onPostExecute()

image.png
简单来说,使用AsyncTask的诀窍就是,在doInBackground()方法中执行具体的耗时任务,在onProgressUpdate()方法中进行UI操作,在onPostExecute()方法中执行一些任务的收尾工作。

服务代码实现:

activity_main.xml:

  1. <service
  2. android:name=".MyService"
  3. android:enabled="true"
  4. android:exported="true"></service>

mainactivity.java

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. //服务
  7. Button start_Service = (Button) findViewById(R.id.start_service);
  8. Button stop_Service = (Button) findViewById(R.id.stop_service);
  9. start_Service.setOnClickListener(this);
  10. stop_Service.setOnClickListener(this); //this指的是什么?是view,也就是当前的图像窗口。
  11. }
  12. @Override
  13. public void onClick(View view) { //重写onclick方法
  14. switch (view.getId()){
  15. case R.id.start_service:
  16. Intent startIntent = new Intent(this, MyService.class);
  17. startService(startIntent);//开始服务
  18. break;
  19. case R.id.stop_service:
  20. Intent stopIntent = new Intent(this,MyService.class);
  21. stopService(stopIntent);//停止服务
  22. break;
  23. default:
  24. break;
  25. }
  26. }
  27. }
  28. //代码对比:紧对比click方法,与本章节service无关。
  29. public class MainActivity extends Activity {
  30. private Button btnOne,btnTwo;
  31. @Override
  32. protected void onCreate(Bundle savedInstanceState) {
  33. super.onCreate(savedInstanceState);
  34. setContentView(R.layout.activity_main);
  35. btnOne = (Button) findViewById(R.id.btnOne);
  36. btnTwo = (Button) findViewById(R.id.btnTwo);
  37. btnTwo.setOnClickListener(new OnClickListener() { //这里就是把onclicklistener方法
  38. //写在setonclicklistener里面
  39. @Override
  40. public void onClick(View v) {
  41. if(btnTwo.getText().toString().equals("按钮不可用")){
  42. btnOne.setEnabled(false);
  43. btnTwo.setText("按钮可用");
  44. }else{
  45. btnOne.setEnabled(true);
  46. btnTwo.setText("按钮不可用");
  47. }
  48. }
  49. });
  50. }
  51. }

MyService.java

  1. package com.example.demon;
  2. import android.app.DownloadManager;
  3. import android.app.Notification;
  4. import android.app.PendingIntent;
  5. import android.app.Service;
  6. import android.content.Intent;
  7. import android.content.IntentFilter;
  8. import android.graphics.Bitmap;
  9. import android.graphics.BitmapFactory;
  10. import android.os.Binder;
  11. import android.os.IBinder;
  12. import android.util.Log;
  13. import androidx.annotation.Nullable;
  14. import androidx.core.app.NotificationCompat;
  15. public class MyService extends Service {
  16. public MyService() {
  17. }
  18. @Override
  19. public IBinder onBind(Intent intent) {
  20. // TODO: Return the communication channel to the service.
  21. throw new UnsupportedOperationException("Not yet implemented");
  22. }
  23. @Override
  24. public void onCreate() {
  25. //每次服务创建时调用
  26. super.onCreate();
  27. Log.d("MyService", "onCreate 执行了");
  28. // Intent intent = new Intent(this, MainActivity.class);
  29. // PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
  30. // Notification notification = new NotificationCompat.Builder(this).setContentTitle("This is the content title").setContentText("This is content text").setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).setContentIntent(pi).build();
  31. // startForeground(1, notification);
  32. }
  33. @Override
  34. public int onStartCommand(Intent intent, int flags, int startId) {
  35. //每次服务启动的时候调用通常情况下,
  36. // 如果我们希望服务一旦启动就立刻去执行某个动作,
  37. // 就可以将逻辑写在onStartCommand()方法里。
  38. // 而当服务销毁时,我们又应该在onDestroy()方法中
  39. // 去回收那些不再使用的资源。
  40. Log.d("MyService", "onStartCommand 执行了");
  41. return super.onStartCommand(intent, flags, startId);
  42. }
  43. @Override
  44. public void onDestroy() {
  45. //每次服务销毁的时候调用
  46. Log.d("MyService", "On Destory 执行了");
  47. super.onDestroy();
  48. }
  49. }
  50. //public class MyService extends Service {
  51. // private DownloadBinder mBinder = new DownloadBinder();
  52. // class DownloadBinder extends Binder{
  53. // //新建了一个类,继承自Binder类
  54. // public void startDownload() {
  55. // Log.d( "My Service", "startDownload executed");
  56. // }
  57. //
  58. // public int getProgress(){
  59. // Log.d("My service", "getProgress executed");
  60. // return 0;
  61. // }
  62. // }
  63. //
  64. // @Nullable
  65. // @Override
  66. // public IBinder onBind(Intent intent) {
  67. // return mBinder;
  68. // }
  69. //}
  70. //创建一个专门的Binder对象来对下载功能进行管理