Service
Service相关
a、Service的特点
不可见、不可交互,在后台运行的四大组件之一。
并不是所有的功能都需要界面。比如音乐播放。
b、Service的启动方式
startService、bindService
c、Service的生命周期
a、通过startService
Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
这种方式,activity和service是相互独立的。如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行
b、通过bindService
Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者解绑了,Service就会调用onUnbind->onDestroyed方法。
这种方式,activity就和service相互捆绑在一起了。所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Service 会调用onUnbind- >onDestroyed方法。
简单来说,startService的方式启动之后,Activity是调用不到Service里面的方法。
bindService方式启动之后,可以得到Service的实例,进而调用Service里面的方法。startService和bindService可以结合使用。无论怎么结合,Service的实例只有一个。
d、为什么使用Service
普通的线程也可以达到在后台做事情的功能,那么为什么使用 Service呢?是因为Service是系统的组件,它的优先级比普通的线程要高,不容易被系统回收。而且线程不好控制, service相对好控制一些。运行在前台的Activity是不会被系统回收的,而Service如果不想被系统回收,就需要在Service中设置一下startForeground(int,Notification)
具体的使用场景有:
a、拥有长连接QQ
b、定时轮询
c、服务里面注册广播接收者。有些广播接收者只能通过代码注册,比如屏幕锁屏、屏幕解锁、电量发生变化等。
e、IntentService
普通的service ,默认运行在ui main 主线程.Sdk给我们提供的方便的、带有异步处理的service类,我们可以在OnHandleIntent() 处理耗时的操作
service的基本用法
关于Service最基本的用法自然就是如何启动一个Service了,启动Service的方法和启动Activity很类似,都需要借助Intent来实现,下面我们就通过一个具体的例子来看一下。
新建一个Android项目,项目名就叫ServiceTest,这里我选择使用4.0的API。
然后新建一个MyService继承自Service,并重写父类的onCreate()、onStartCommand()和onDestroy()方法,如下所示:
- public class MyService extends Service {
- public static final String TAG = "MyService";
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d(TAG, "onCreate() executed");
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "onStartCommand() executed");
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.d(TAG, "onDestroy() executed");
- }
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
- }
可以看到,我们只是在onCreate()、onStartCommand()和onDestroy()方法中分别打印了一句话,并没有进行其它任何的操作。
然后打开或新建activity_main.xml作为程序的主布局文件,代码如下所示:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <Button
- android:id="@+id/start_service"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Start Service" />
- <Button
- android:id="@+id/stop_service"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Stop Service" />
- </LinearLayout>
我们在布局文件中加入了两个按钮,一个用于启动Service,一个用于停止Service。
然后打开或新建MainActivity作为程序的主Activity,在里面加入启动Service和停止Service的逻辑,代码如下所示:
- 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;
- }
- }
- }
可以看到,在Start Service按钮的点击事件里,我们构建出了一个Intent对象,并调用startService()方法来启动MyService。然后在Stop Serivce按钮的点击事件里,我们同样构建出了一个Intent对象,并调用stopService()方法来停止MyService。代码的逻辑非常简单,相信不需要我再多做解释了吧。
另外需要注意,项目中的每一个Service都必须在AndroidManifest.xml中注册才行,所以还需要编辑AndroidManifest.xml文件,代码如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.servicetest"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="14"
- android:targetSdkVersion="17" />
- <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>
- </manifest>
这样的话,一个简单的带有Service功能的程序就写好了,现在我们将程序运行起来,并点击一下Start Service按钮,可以看到LogCat的打印日志
也就是说,当启动一个Service的时候,会调用该Service中的onCreate()和onStartCommand()方法。
那么如果我再点击一次Start Service按钮呢?这个时候的打印日志如下:
可以看到,这次只有onStartCommand()方法执行了,onCreate()方法并没有执行,为什么会这样呢?
这是由于onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样调用startService()方法,onCreate()方法都不会再执行。因此你可以再多点击几次Start Service按钮试一次,每次都只会有onStartCommand()方法中的打印日志。
我们还可以到手机的应用程序管理界面来检查一下MyService是不是正在运行,如下图所示:
恩,MyService确实是正在运行的,即使它的内部并没有执行任何的逻辑。
回到ServiceTest程序,然后点击一下Stop Service按钮就可以将MyService停止掉了。