后台服务(Service)简述

一、简介

Service是应用的后台服务,它用来执行不需与用户交互的、耗时的操作,或者给其他应用提供一些功能。Service默认运行在用户界面(Activity)所在的主线程中,所以它的执行速度越快越好。如果有耗时较长或者会阻塞的操作,可以在Service中创建一个线程去完成它。若Service的执行时间超过5秒,系统会抛出“应用程序无响应(ANR)”的对话框。

二、注册Service

所有Service都应该在所在应用的AndroidManifest.xml中注册相应的标签,否则将无法被Activity连接(包括start和bind)。

<manifest ... >  

  ...  

  <application ... >  

      <service 
            <!-- 设置本服务的类名 -->
            android:name=".TestService" 
            <!-- 设置本服务作为一个单独的进程。省略这行代码的话,它将运行于主线程中 -->
            android:process=":任意名称"
            <!-- 是否接收其他应用的启动请求 -->
            android:exported="false"
      />  

      ...  

  </application>  

</manifest>

三、连接Service

Service可以同时被多个Activity经调用startService()或bindService()来连接,每次它都会以onStartCommand()或onBind()来响应,但其onCreate()只会在Service对象首次创建时调用。如果不想提供绑定,可以让onBind()返回null。

四、断开Service

绑定上的Activity可以调用unbindService()来解除绑定。当所有Activity都解绑后,系统就会调用服务的onUnbind()方法(若无其他Activity启动服务,则服务会被销毁)。启动服务的Activity可以调用stopService()来停止服务,服务也可以自己调用stopSelf()来停止,但这两种方法的前提是服务未被绑定。停止时,系统会调用onDestory()来销毁服务。

后台服务(Service)简述_第1张图片

五、生命周期

Service的生命周期从onCreate()开始,到onDestroy()或者被系统杀死时结束。在空闲内存不足时,系统会杀掉一些进程,Service已启动的时间越长,越容易被系统杀死。在Service被可见进程所绑定期间,它所在的进程也将被认为是可见进程(除非绑定时另行指定),使得它的进程不那么容易被杀死。当Service正在运行onCreate()、onStartCommand()、onDestory()时,或者调用了startForeground(),系统会把它所在的进程当做前台进程,这样只有在极端低内存的情况下它的进程才会被杀死。

六、线程安全

Android提供了一个线程安全的、继承自Service的IntentService类,继承它之后只需实现其onHandleIntent方法则可,该方法负责具体的工作任务。IntentService仅支持startService(),而不支持bindService()。每当有Activity连接上来时,它都会创建一个工作线程加入到由它管理的工作队列中。工作线程们依次调用onHandleIntent(),执行完毕后才轮到下一个。当所有的工作线程都干完活时,IntentService对象会自动销毁,以节省资源。

public class TestIntentService extends IntentService {
    public IntentService() 
    {
        super("随便起个名字");
    }

    protected void onHandleIntent(Intent intent)
    {
        /** * 工作线程们依次进来干活,执行完毕后才轮到下一个。 * 任务相关信息会经由startService(intent)的参数传进来。 */
    }
}

七、样例代码

package com.example.wesnoth;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;

public class TestActivity extends Activity {
    private Intent intent = new Intent(TestActivity.this, TestService.class);
    private TestService.MyBinder myBinder = null;
    private TestServiceConnection testServiceConnection = new TestServiceConnection();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.XXXXXXX);
        // 注意:应当使用指定了目标Service类名的
        // 显式Intent来启动Service。
        // 否则Android 5.0(API 21)以上系统会抛出异常
        Intent intent = new Intent(this, DownloadService.class);
        if (true)
        {
            /** * 启动服务。 */
            startService(intent);
        }
        else
        {
            /** * 绑定服务。 */
            bindService(intent, testServiceConnection, BIND_AUTO_CREATE);
        }
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        if(true)
        {                   
            /** * 停止服务。 * 此时不管是否有其他Activity连接,都会进入到Service.onDestroy() */
            stopService(intent);
        }
        else
        {
            /** * 解绑服务 */
            unbindService(intent);
        }
    }

    class TestServiceConnection implements ServiceConnection
    {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            /** * 当绑定Service成功时,进入此方法 */
            myBinder = (TestService.MyBinder)service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            /** * 当Service所在的进程崩溃掉或者被杀掉时,进入此方法。 * 此时并不会断开与Service的连接,等到Service所在的进程重启时, * 会重新调用onServiceConnected() */
            myBinder = null;
        }
    }

}
package com.example.wesnoth;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;


public class TestService extends Service {
    private MyBinder myBinder = new MyBinder();

    @Override
    public void onCreate()
    {
        /** * 本方法只会在Service对象首次创建时调用。 */
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        // 可以在这里创建处理任务的线程。
        // 线程完成任务后可以调用stopSelf(startId);
        // 如果最后一个启动服务的ID与startId匹配,
        // 就会销毁服务,否则不销毁。

        /** * 当有Context对象调用startService()时,调用此方法。 */
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        /** * 当首次被Activity绑定时,调用此方法。 * 系统会保存IBinder, * 后续的绑定将不调用此方法而是直接返回它。 * 如果不想提供绑定,可以返回null */
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent)
    {
        /** * 当所有已绑定的Activity都调用了unbindService()来解绑, * 就会调用onUnbind()。 */
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy()
    {
        /** * 当所有已绑定的Activity都调用了unbindService()来解绑, * 此时若没有任何Activity已通过startService来连接的话,才会调用onDestory()。 * 若某个Activity调用了stopService,或者Service自己调用了stopSelf(), * 此时不管还有没有其他连接,都会调用onDestroy()。 */
        super.onDestroy();
    }

    // 注意:这个Binder的所有公开方法都需要做到线程安全
    public class MyBinder extends Binder {
        // 这个方法可以给bind上的Activity调用
        public void doSomething()
        {
            // 处理任务
        }
    }
}

你可能感兴趣的:(service,Androi后台服务)