Service

来源:互联网 发布:java 密码加密解密 编辑:程序博客网 时间:2024/06/05 06:41

Service(服务)

  • 服务是 Android 中实现程序后台运行的解决方案,适合执行不需要和用户交互长期运行的任务。
  • 应用进程被杀掉,所依赖该进程的服务也终止。
  • 服务不会自动开启线程,默认运行在主线程。
  • 服务内部创建子线程,并实现业务处理。

[Android 多线程编程]

  • 耗时操作放在子线程运行,否则主线程会被阻塞

<线程的基本用法>

1.实现Runnable接口实现

class MyThread implements Runnable{    public void run(){        //处理具体的业务逻辑    }}MyThread myThread = new MyThread();new Thread(myThread).start();

2.匿名类写法(常用)

new Thread(new Runnable(){    public void run(){        //处理具体的业务逻辑    }}).start();

<在子线程中更新UI>

Android UI 是线程不安全的,要更新UI,必须在主线程当中

  • 很简单,异步处理机制可以解决子线程中进行UI操作的问题
public static final int UPDATE_TEXT = 1;public Handler handler = new Handler(){    public void handleMessage(Message msg){        switch(msg.what){        case UPDATE_TEXT:        //在这里进行UI操作        break;        default:        break;        }    }};public void onClick(){    new Thread(new Runnable(){        Message message = new Message();        message.what = UPDATE_TEXT;        handler.sendMessage(message); // 将 Message 对象发出去    }).start();}

运用 Message 把消息传递出去交由 handleMessage 来处理业务逻辑


<解析异步消息处理机制>

  • 很简单,Android 中异步消息处理主要由四个部分组成:
    1. Message
      • Message 是线程之间传递的消息,它可以携带少量的信息在线程之间交换数据
        例如:arg1、arg2 字段携带整型数据;obj 字段携带一个 Object 对象;what 字段携带…
    2. Handler
      • Handler(处理者)主要是用于发送处理消息的。
        发送:sendMessage()
        处理:handleMessage()
    3. MessageQueue
      • 消息队列,存放 Handler 发送的消息。
      • 消息会一直存放在 MessageQueue 中等待被处理
      • 每个线程只会有一个 MessageQueue 对象
    4. Looper
      • 管理 MessageQueue 。调用 Looper 的 loop() 方法后,就会进入一个无限循环,只要 MessageQueue 中存在一条消息,就会将它取出并传递到 handleMessage() 中处理。
      • 每个线程只有一个 Looper 对象

这里写图片描述


<使用AsyncTask>

  • 借助 AsyncTask 也可以很简单地从子线程切换到主程序(背后的实现原理也是基于异步消息处理机制,android 已经封装好了

AsyncTask 泛型三参数:
第一:Params 在执行 AsyncTask 时使用;在后台任务中使用

第二:Progress 后台任务执行时需要在界面显示当前进度时使用;作为进度单位

第三:Result 后台任务执行完毕,需要对结果进行返回时使用;作为返回值类型

class DownloadTask extends AsyncTask<Void, Integer, Boolean>{    // void 不需要传入参数给后台任务;Integer 整型数据来作为进度显示单位; Boolean 布尔型数据来反馈执行结果}
  • 重写 AsyncTask 中的方法,完成对任务的定制。常用四个方法:
    1. onPreExecute()
      • 后台任务开始执行前调用
      • 用于界面初始化操作。 eg:显示进度条对话框
    2. doInBackground(Params…)
      • 这个方法的代码会在子线程中运行,这儿处理耗时任务。
      • 任务完成 return AsyncTask 泛型第三个参数类型的结果,为空不返回。
      • 不可以进行UI操作。如果需要 UI 操作调用 publishProgress(Progress…) 方法
    3. onProgressUpdate(Progress…)
      • 后台任务调用 publishProgress(Progress…) ,这个方法就被调用。
      • 参数由后台任务传进
      • 在此方法中更新 UI
    4. onPostExecute(Result)
      • 后台任务通过 return 返回时,此方法被调用
      • 利用返回的数据进行 UI 操作
class DownloadTask extends AsyncTask<Void, Integer, Boolean>{    // 后台任务执行前    protected void onPreExecute(){        progressDialog.show(); //显示进度对话框    }    // 后台任务执行中(此方法即在子线程中跑)    protected Boolean doInBackground(Void... params){        try{            int downloadPercent = doDownload(); //虚构方法            publishProgress(downloadPercent);            if(downloadPercent >= 100){                break;            }        }catch(Exception e){            return false;        }        return true;    }    // 后台任务调用 publishProgress()时    protected void onProgressUpdate(Integer... values){        progressDialog.setMessage("Downloaded" + values[0] + "%");//更新下载进度    }    //  后台任务通过 return 时    protected void onPostExecute(Boolean result){        progressDialog.dismiss();//关闭对话框        if(result){            Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show();        }else{            Toast.makeText(context, "Download failed", Toast.LENGTH_SHORT).show();        }    }}//启动new DownloadTask().execute();

AsyncTask 诀窍:在 doInBackground() 中执行具体耗时任务,在 onProgressUpdate() 中进行UI操作,在 onPostExecute()中执行一些任务收尾工作

[服务的基本用法]


<定义一个服务>

1、新建一个 MyService 类,继承 Service
- onBind() 方法是 Service 唯一的抽象方法,必须在子类中实现

public class MyService extends Service{    @Override    public IBinder onBind(Intent intent){        return null;    }}

2、服务常用的三个方法

  • onCreate()
    • 服务创建时候调用(仅创建那一次
  • onStartCommand(Intent intent, int flags, int startId)
    • 每次启动服务时调用
  • onDestroy()
    • 服务销毁的时调用

3、在 AndroidManifest.xml 中注册服务

<application....>    <service android:name=".MyService">    </service></application>

<启动和停止服务>

  • 借助 Intent 实现
public void onClick(View v){    switch(v.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;    }}

<活动和服务进行通信>

  • onBind() 活动(Activity)指挥服务(Service)去干什么

活动开启、查看服务下载功能的例子:

服务(Service)

public class MyService extends Service{// (2)实例化内部类    private DownloadBinder mBinder = new DownloadBinder();// (1)创建内部类    class DownloadBinder extends Binder{        public void startDownload(){            //执行下载逻辑        }        public int getProgress(){            //执行查看下载状态逻辑        }// (3)返回内部类实例        @Override        pubilc IBinder onBind(Intent intent){            return mBinder;        }    }}

活动(Activity)

private MyService.DownloadBinder downloadBinder; // 下载服务//创建匿名类。重写解除绑定时调用的 onServiceDisconnected() 方法,绑定时调用的 ServiceConnected() 方法private ServiceConnection connection = new ServiceConnection(){    @Override    public void onServiceDisconnected(ComponentName name){        // 解除绑定的时候调用    }    @Override    public void ServiceConnected(ComponentName name, IBinder service){        //绑定时调用        downloadBinder = (MyService.DownloadBinder) service;        downloadBinder.startDownload();        downloadBinder.getProgress();    }};    @Override    public void onClick(View v){        switch(v.getId()){        case R.id.bind_service:            Intent bindIntent = new Intent(this, MyService.class);            bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务        break;        case R.id.unbind_service:            unbindService(connection); //解绑服务        break;        default:        break;    }}

<服务的生命周期>

  • 不管你调用了多少次 startService() 方法,只需要调用一次 stopService() 或 stopSelf() 方法,服务就会停止下来。
  • 服务没创建过,onCreate() 方法优先于任何方法执行。
  • 执行了 stopService() 和 unbindService() 都会调用 onDestroy() 方法。一个服务同时调用了 startService() 和 bindService() 要销毁服务必须同时调用stopService() 和 unbindService() 服务才会执行 onDestroy()。

    • 开启服务且绑定了服务,必须关闭且解绑才能销毁服务

    这里写图片描述

[服务的更多技巧]


<使用前台服务>

public class MyService extends Service{    ...    @Override    public void onCreate(){        ...        Notification notification = new Notification(R.drawable.ic_launcher, "Notification comes", System.currentTimeMillis());        Intent notificationIntent = new Intent(this, MainActivity.class);        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);        notification.setLatestEventInfo(this, "This is title", "This is content", pendingIntent);        startForeground(1, notification);        ...    }    ...}

没有调用 NotificationManage 的 notify() 来将通知显示出来,而是调用了startForegrounnd( 第一:id第二:Notification对象 ),调用此方法就会让服务变成一个前台服务并在系统状态栏显示出来。


<使用IntentService>

  • 如果在服务里处理耗时操作会出现 ANR(Application Not Responding)情况。因此可以借助 Android 的多线程技术,即标准的服务形式如下:
public class MyService extends Service{    @Override    public IBinder onBind(Intent intent){        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId){        new Thread(new Runnable(){            @Override            public void run(){                //处理具体逻辑                stopSelf(); //此服务开启后会一直处于运行状态。要想让它执行完毕后自动停止应进行此操作            }        }).start();        return super.onStartCommand(intent, flags, startId);    }}
  • 总会有程序员忘记开启线程,并调用 stopSelf() 方法,因此 Android 提供了一个 IntentService类 来创建一个异步的会自动停止的服务

1、服务 Service

public class MyIntentService extends IntentService{    public MyIntentService(){        super("MyIntentService"); // 调用父类的有参构造函数    }    @Override    protected void onHandleIntent(Intent intent){        //处理一些具体的逻辑,而且不用担心ANR的问题。此方法已经在子线程中运行了    }    @Override    public void onDestroy(){        //这个服务在运行结束后会自动停止        super.onDestroy();    }}

2、活动 Activity

Intent intentService = new Intent(this, MyIntentService.class);startService(intentService);

3、AndroidManifest 注册

<service android:name=".MyIntentService"></service>
0 0
原创粉丝点击