Service的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wu_wxc/article/details/51377512

转载请标明出处:http://blog.csdn.net/wu_wxc/article/details/51377512
本文出自【吴孝城的CSDN博客】

关于Service的生命周期,可以看:Services的生命周期

IntentService

如果程序不需要同时处理多个请求,IntentService将是最好的选择。

可以启动IntentService多次,每一次耗时操作都会以队列的形式在IntentService的onHandleIntent回调方法中执行,每次只执行一个工作线程,执行完再执行下一个。这种单线程形式保证了主线程(UI线程)不会被阻塞

处理完所有的启动请求后,IntentService会自动停止服务,所以不需要调用stopSelf()来停止服务。

提供缺省的onBind()实现代码,因为不提供绑定,所以它返回null。

提供缺省的onStartCommand()实现代码,它把intent送入工作队列,稍后会再传给你的onHandleIntent()实现代码。

以上所有的步骤汇成一个结果,我们需要做的就是实现onHandleIntent()来完成客户端提交的任务,还有就是为服务提供一小段构造方法

以下是一个IntentService的实现例子:

public class MyIntentService extends IntentService {

    //必须实现一个构造方法,且以工作线程名称作为参数
    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * 从缺省的工作空间调用本方法,并用启动服务的Intent作为参数
     * 本方法返回后,IntentService会适时终止这个服务
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        // 我们可以在这里执行一些工作,如下载文件等
    }

}

如果想重写其他回调方法,要确保调用一下父类的实现代码以便IntentService能正确处理工作线程的生命周期。
下面程序回调了Service生命周期的其他方法
这里写图片描述
MainActivity.java

package cn.wuxiaocheng.intentservice;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onHandleIntent(View v) {
        startService(new Intent(MainActivity.this, MyIntentService.class));
    }
}
MyIntentService.java
package cn.wuxiaocheng.intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;

public class MyIntentService extends IntentService {

    //必须实现一个构造方法,且以工作线程名称作为参数
    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * 从缺省的工作空间调用本方法,并用启动服务的Intent作为参数
     * 本方法返回后,IntentService会适时终止这个服务
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        //我们可以在这里执行一些工作,如下载文件等
        try {
            //作为演示,这里我让它休息3秒,然后输出onHandleIntent
            Thread.sleep(3000);
            System.out.println("onHandleIntent");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCreate() {
        System.out.println("onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void setIntentRedelivery(boolean enabled) {
        super.setIntentRedelivery(enabled);
        System.out.println("setIntentRedelivery");
    }

    @Override
    public IBinder onBind(Intent intent) {
        //不支持绑定,所以返回null
        return null;
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
        super.onDestroy();
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="cn.wuxiaocheng.intentservice.MainActivity">

    <Button
        android:onClick="onHandleIntent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="onHandleIntent" />
</RelativeLayout>
还有要在配置清单文件里添加声明 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.wuxiaocheng.intentservice">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyIntentService"
            android:exported="false"></service>
    </application>

</manifest>
其中第19-21行就是

Service

下面说下继承Service的使用
如果Service需要多线程运行,可以继承Service来完成每个Intent处理。
对于每一个启动请求,它都以一个工作线程来完成处理,并且每次只处理一个请求。因为是自行处理每个onStartCommand()调用,所以可以为每个请求创建一个新的线程,并立即运行它们,不需要等待前一个请求处理完毕。这就实现了多线程的操作。


来个小例子
这里写图片描述
MainActivity.java
package cn.wuxiaocheng.started;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
    }

    public void startService(View v) {
        startService(intent);
    }

}

MyService.java

package cn.wuxiaocheng.started;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;

public class MyService extends Service {

    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;

    //程序从线程接收消息
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 通常我们在这里执行一些操作,如下载文件
            // 这里我们让它休息3秒
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                //恢复中断状态
                Thread.currentThread().interrupt();
            }
            //通过startId来停止服务,这样我们就不用在处理其他工作的过程中再来停止服务
            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate() {
        // 启动运行服务的线程
        // 注意要创建一个单独的线程,因为服务通常运行于进行的主线程中,我们不想阻塞主线程
        // 还要赋予它后台服务的保优先级,这样处理密集的工作就不会干扰我们的UI
        HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        // 获得HandlerThread的Looper的队列并用于Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
        System.out.println("onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("service starting");

        // 对于每一个请求,都发送一个消息来启动处理。
        // 同时传入启动ID,以便任务完成后我们知道该终止哪一个请求
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);

        // 如果我们被杀死,那从这里返回后被重启
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // 不提供绑定,所有返回null
        return null;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="cn.wuxiaocheng.started.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="startService"
        android:text="startService" />
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.wuxiaocheng.started">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

</manifest>

onStartCommand()的返回值必须是以下常量之一 START_NOT_STICKY 在onStartCommand()返回后,如果系统kill这个服务,系统不会自动重启这个服务,直到startService(Intent intent)方法再次被调用。 START_STICKY 如果系统在onStartCommand()后杀死了这个服务,则将重启并调用onStartCommand(),但不会再次传入一个intent,而是用null的intent来调用onStartCommand(),如果还有启动服务的intent未发送完,那么这些剩下的intent会继续发送。这适用于媒体播放器(或类似服务),它们不执行命令,但需要一直运行并随时待命。 START_REDELIVER_INTENT 如果系统在onStartCommand()返回后杀死了服务,则将重建服务并用上一个已送过的intent调用onStartCommand()。任何未发送完的intent也都会依次送入。这适用于那些需要立即恢复工作的活跃服务,比如下载文件。

Started:非绑定服务

package cn.wuxiaocheng.started;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

public class MyService extends Service {

    public MyService() {
    }

    @Override
    public void onCreate() {
        //线程开始被创建
        System.out.println("onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //启动线程后执行的内容
        System.out.println("onStartCommand");
        // 服务被杀死看后的表现
        return START_STICKY ;
    }

    @Override
    public void onDestroy() {
        //线程摧毁
        System.out.println("onDestroy");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //不允许绑定,所有返回null
        return null;
    }
}

Bound:绑定服务

MyService.java

package cn.wuxiaocheng.bound;

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

public class MyService extends Service {

    IBinder mBinder;      // 客户端绑定接口
    boolean mAllowRebind; // 声明是否使用onRebind

    public MyService() {
    }

    @Override
    public void onCreate() {
        //服务被创建
        System.out.println("onCreate");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // 客户端调用bindService()绑定服务
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        //所有扩客户端都通过unbindService()解除绑定
        return mAllowRebind;
    }

    @Override
    public void onDestroy() {
        //服务被摧毁
        System.out.println("onDestroy");
    }
}


android:exported
该属性决定该服务是否能够被其他应用程序组件调用或跟它交互。值为true时,能够被调用或交互,值为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。

android:enabled
该属性决定系统是否能实例化这个服务,值为true时,则能够被实例化,值为false时,不能被实例化,默认值为true

猜你喜欢

转载自blog.csdn.net/wu_wxc/article/details/51377512
今日推荐