Android Service中方法使用详细介绍

   Android Service中方法使用详细介绍

  在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务。例如,一个从service播放音乐的音乐播放器,应被设置为前台运行,因为用户会明确地注意它的运行.在状态栏中的通知可能会显示当前的歌曲并且允许用户启动一个activity来与音乐播放器交互。

  Service的两种实现形式

  1.非绑定

  通过调用应用程序组件(例如Activity)的startService()方法来启动一个服务.一旦启动,服务就会在后台一直运行,即使应用程序组件此时被关闭.通常,已经启动的服务会处理一些单一功能,并且也不需要返回结果给调用者.例如,在网络上下载或上传文件.当服务的工作处理结束,才会自己关闭服务.

  2.绑定(bind)

  通过调用应用程序组件的bindService()方法来绑定一个服务.已绑定的服务会提供一个客户端-服务端交互接口.该接口主要用来与应用程序交互,发送请求,获取结果,甚至通过IPC来访问进程.只要一个程序组件绑定服务就会运行绑定服务,多个应用程序组件可以同时时间绑定一个服务.当所有的应用程序组件都解除绑定,该绑定服务器就会被销毁.

  实现service的方法介绍

  onStartCommand()

  系统在其它组件比如activity通过调用startService()请求service启动时调用这个方法.一旦这个方法执行,service就启动并且在后台长期运行.如果你实现了它,你需要负责在service完成任务时停止它,通过调用stopSelf()或stopService().(如果你只想提供绑定,你不需实现此方法).

  OnBind()

  当组件调用bindService()想要绑定到service时(比如想要执行进程间通讯)系统调用此方法.在你的实现中,你必须提供一个返回一个IBinder来以使客户端能够使用它与service通讯,你必须总是实现这个方法,但是如果你不允许绑定,那么你应返回null.

  OnCreate()

  系统在service第一次创建时执行此方法,来执行只运行一次的初始化工作(在调用它方法如onStartCommand()或onBind()之前).如果service已经运行,这个方法不会被调用.

  OnDestroy()

  系统在service不再被使用并要销毁时调用此方法.你的service应在此方法中释放资源,比如线程,已注册的侦听器,接收器等等.这是service收到的最后一个调用.

  如果一个组件通过调用startService()启动一个service(最终导致onStartCommand()被调用),之后service会保持运行,直到它通过stopSelf()停止自己或另外的组件调用stopService()停止它.

  service实现代码

  1.非绑定

  新建一个MyService继承自Service,并重写父类的onCreate()、onStartCommand()和onDestroy()方法

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
// IntentService会使用单独的线程来执行该方法的代码
// 该方法内执行耗时任务,比如下载文件,此处只是让线程等待20秒
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("----耗时任务执行完成---");
}
}

  我们在布局文件中加入了两个按钮,一个用于启动Service,一个用于停止Service。

  然后打开或新建MainActivity作为程序的主Activity,在里面加入启动Service和停止Service的逻辑,代码如下所示:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

public class MainActivity extends Activity implements OnClickListener {
private Button startService;
private Button stopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService = (Button) findViewById(R.id.start_service);
stopService = (Button) findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
}
@Override
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;
}
}

  项目中的每一个Service都必须在AndroidManifest.xml中注册才行,所以还需要编辑AndroidManifest.xml文件,代码如下所示:

  ?

1
2
3
4
5
6
7
8
9

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
……
<service android:name="com.example.servicetest.MyService" >
</service>
</application>

  周期分析

  onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样调用startService()方法,onCreate()方法都不会再执行。因此你可以再多点击几次Start Service按钮试一次,每次都只会有onStartCommand()方法中的打印日志。

  2.绑定的service

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
public class LocalBinder extends Binder {
LocalService getService() {
// 返回本service的实例到客户端,于是客户端可以调用本service的公开方法
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**客户端所要调用的方法*/
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}

  下面是一个绑定到LocalService并且在按钮按下时调用getRandomNumber()的actvity的例子:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// 绑定到类LocalService的实例
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// 从service解除绑定
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** 当按钮按下时调用(在layout文件中定义的button并用android:onClick 属性指定响应到本方法) */
public void onButtonClick(View v) {
if (mBound) {
// 调用LocalService的一个方法
// 然而,如果这个调用中有挂起操作,那么这个请求应发
// 生在另一个线程来避免拉低activity的性能.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** 定义service绑定的回调,传给bindService() 的*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
//我们已经绑定到了LocalService,把IBinder进行强制类型转换并且获取LocalService实例.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

  service的周期函数

  1、当采用Context.startService()方法启动服务,与之有关的生命周期方法

  onCreate()–> onStart()–> onDestroy()

  onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。

  onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。

  onDestroy()该方法在服务被终止时调用。

  2、 当采用Context.bindService()方法启动服务,与之有关的生命周期方法

  onCreate()–> onBind() –> onUnbind() –> onDestroy()

  onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

  onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。

  如果先采用startService()方法启动服务,然后调用bindService()方法绑定到服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务,触发的生命周期方法如下:

  onCreate()–>onStart()–>onBind()–>onUnbind()[重载后的方法需返回true–>onRebind()

  那么如果我们既点击了Start Service按钮,又点击了Bind Service按钮会怎么样呢?

  这个时候你会发现,不管你是单独点击Stop Service按钮还是Unbind Service按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

  Service和Thread的区别

  主要就是因为Service的后台概念。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但是,如果我告诉你Service其实是运行在主线程里的,所以是没有任何关系的。

  Service又有何用呢?

  其实大家不要把后台和子线程联系在一起就行了,这是两个完全不同的概念。

  Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。

  比如说一些应用程序,始终需要与服务器之间始终保持着心跳连接,就可以使用Service来实现。你可能又会问,前面不是刚刚验证过Service是运行在主线程里的么?在这里一直执行着心跳连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。

  使用service创建线程和activity直接创建线程的区别

  Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

  IntentService介绍

  IntentService是Service的子类,比普通的Service增加了额外的功能。

  先看Service本身存在两个问题:

  Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;

  Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;

  二、IntentService特征

  会创建独立的worker线程来处理所有的Intent请求;

  会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;

  所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;

  为Service的onBind()提供默认实现,返回null;

  为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;

  实现

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
// IntentService会使用单独的线程来执行该方法的代码
// 该方法内执行耗时任务,比如下载文件,此处只是让线程等待20秒
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("----耗时任务执行完成---");
}
}

  activity代码

  ?

1
2
3
4
5

public void startIntentService(View source) {
// 创建需要启动的IntentService的Intent
Intent intent = new Intent(this, MyIntentService.class);
startService(intent);  

时间: 2024-12-02 15:26:50

Android Service中方法使用详细介绍的相关文章

Android Service中方法使用详细介绍_Android

 service作为四大组件值得我们的更多的关注 在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务.例如,一个从service播放音乐的音乐播放器,应被设置为前台运行,因为用户会明确地注意它的运行.在状态栏中的通知可能会显示当前的歌曲并且允许用户启动一个activity来与音乐播放器交互. Service的两种实现形式 1.非绑定 通过调用应用程序组件(例如Activity)的startService()方法来启动一个服务.一旦启动,服务就会在

基于Android Service 生命周期的详细介绍_Android

Service概念及用途: Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行,那我们什么时候会用到Service呢?比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当我们退出播放音乐的应用,如果不用Service,我们就听不到歌了,所以这时候就得用到Service了,又比如当我们一个应用的数据是通过网络获取的,不同时间(一段时间)的数据是不同的这时候我们可以用Ser

Android Service中使用Toast无法正常显示问题的解决方法_Android

本文实例讲述了Android Service中使用Toast无法正常显示问题的解决方法.分享给大家供大家参考,具体如下: 在做Service简单练习时,在Service中的OnCreate.OnStart.OnDestroy三个方法中都像在Activity中同样的方法调用了Toast.makeText,并在Acitivy中通过两个按钮来调用该服务的onStart和onDestroy方法: DemoService代码如下: @Override public void onCreate() { su

Android Activity的生命周期详细介绍

Android Activity的生命周期详细介绍 生命周期描述的是一个类从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法.在这个过程中,会针对不同的生命阶段调用不同的的方法. Activity是Android中四大组件之一,是最常见的应用组件,也是用的最多的组件,它能够提供一个界面与用户进行交互.Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:onCreate  onDestory  onStart  onStop  onRes

PHP中的命名空间详细介绍

  这篇文章主要介绍了PHP中的命名空间详细介绍,本文讲解了命名空间(namespace)的概念.正在使用命名空间.定义命名空间.子命名空间.从命名空间中调用代码等内容,需要的朋友可以参考下 概述 PHP对于命名空间的支持,经历了一段艰难的旅程.幸运的是,PHP从5.3开始引入了命名空间.自从PHP引入了命名空间,PHP代码的适用结构也得到了大大的改善.许多编程语言早就有了命名空间的概念,相对于其他语言来说,PHP对于命名空间的支持,稍微有点晚了.不管如何,每一种新特性的引入都有其目的,和其他语

unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)_Android

unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk),总的流程分为以下6个步骤: 1.安装java_jdk 2.配置java环境变量 3.更新android的sdk 4.从Unity3d中发布出apk文件 5.创建android虚拟机并运行 6.将apk文件安装到android虚拟机中 (为方便新手,在下面对每个步骤的具体操作及可能遇到的问题详细提一下) 1.安装java_jdk 官网(www.java.com),免费,我安装的文件的名字是j

unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)

unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk),总的流程分为以下6个步骤: 1.安装java_jdk 2.配置java环境变量 3.更新android的sdk 4.从Unity3d中发布出apk文件 5.创建android虚拟机并运行 6.将apk文件安装到android虚拟机中 (为方便新手,在下面对每个步骤的具体操作及可能遇到的问题详细提一下) 1.安装java_jdk 官网(www.java.com),免费,我安装的文件的名字是j

Android 中的注解详细介绍_Android

注解是我们经常接触的技术,Java有注解,Android也有注解,本文将试图介绍Android中的注解,以及ButterKnife和Otto这些基于注解的库的一些工作原理. 归纳而言,Android中的注解大概有以下好处 提高我们的开发效率 更早的发现程序的问题或者错误 更好的增加代码的描述能力 更加利于我们的一些规范约束 提供解决问题的更优解 准备工作 默认情况下,Android中的注解包并没有包括在framework中,它独立成一个单独的包,通常我们需要引入这个包. dependencies

Android中的WebView详细介绍_Android

Android中WebView的详细解释: 1. 概念: WebView(网络视图)能加载显示网页,可以将其视为一个浏览器.它使用了WebKit渲染引擎加载显示网页. 2. 使用方法: (1).实例化WebView组件: A.在Activity中实例化WebView组件.eg: 复制代码 代码如下:    WebView webView = new WebView(this); B.调用WebView的loadUrl()方法,设置WevView要显示的网页.eg: 复制代码 代码如下: 互联网用