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 中异步消息处理主要由四个部分组成:
- Message
- Message 是线程之间传递的消息,它可以携带少量的信息在线程之间交换数据
例如:arg1、arg2 字段携带整型数据;obj 字段携带一个 Object 对象;what 字段携带…
- Message 是线程之间传递的消息,它可以携带少量的信息在线程之间交换数据
- Handler
- Handler(处理者)主要是用于发送和处理消息的。
发送:sendMessage()
处理:handleMessage()
- Handler(处理者)主要是用于发送和处理消息的。
- MessageQueue
- 消息队列,存放 Handler 发送的消息。
- 消息会一直存放在 MessageQueue 中等待被处理
- 每个线程只会有一个 MessageQueue 对象
- Looper
- 管理 MessageQueue 。调用 Looper 的 loop() 方法后,就会进入一个无限循环,只要 MessageQueue 中存在一条消息,就会将它取出并传递到 handleMessage() 中处理。
- 每个线程只有一个 Looper 对象
- Message
<使用AsyncTask>
- 借助 AsyncTask 也可以很简单地从子线程切换到主程序(背后的实现原理也是基于异步消息处理机制,android 已经封装好了)
AsyncTask 泛型三参数:
第一:Params
在执行 AsyncTask 时使用;在后台任务中使用
第二:Progress
后台任务执行时需要在界面显示当前进度时使用;作为进度单位
第三:Result
后台任务执行完毕,需要对结果进行返回时使用;作为返回值类型
class DownloadTask extends AsyncTask<Void, Integer, Boolean>{ // void 不需要传入参数给后台任务;Integer 整型数据来作为进度显示单位; Boolean 布尔型数据来反馈执行结果}
- 重写 AsyncTask 中的方法,完成对任务的定制。常用四个方法:
- onPreExecute()
- 后台任务开始执行前调用
- 用于界面初始化操作。 eg:显示进度条对话框
- doInBackground(
Params
…)- 这个方法的代码会在子线程中运行,这儿处理耗时任务。
- 任务完成 return AsyncTask 泛型第三个参数类型的结果,为空不返回。
- 不可以进行UI操作。如果需要 UI 操作调用 publishProgress(Progress…) 方法
- onProgressUpdate(
Progress
…)- 后台任务调用 publishProgress(Progress…) ,这个方法就被调用。
- 参数由后台任务传进
- 在此方法中更新 UI
- onPostExecute(
Result
)- 后台任务通过 return 返回时,此方法被调用
- 利用返回的数据进行 UI 操作
- onPreExecute()
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>
- Service
- Service
- service
- Service
- service
- Service
- Service
- service
- Service
- Service
- Service
- service
- service
- Service
- Service
- Service
- Service
- Service
- 1019 Least Common Multiple
- make版本替换
- 使用MyBatis操作数据库连接
- 冒泡排序示例
- Error:Execution failed for task ':app:mergeDebugResources
- Service
- linux fork()笔记
- 自己解决基于MQTT的android推送
- LeetCode 94 Binary Tree Inorder Traversal (中序遍历二叉树)
- AngularJS ui-router (嵌套路由)
- 装配Bean:XML与JavaConfig混合装配
- DBN学习资料
- Netmask (子网掩码 )的用途与子网络的切分
- Androidstudio工具下的JNI开发环境搭建