【我的Android进阶之旅】IntentService详解

一.前言

我们都知道Service是运行在主线程中的一种后台机制,如果在service中执行耗时操作,就可能会导致ANR。那么在不使用IntentService的时候,我们在service中进行耗时操作都是怎么处理的呢,下面上伪代码

public class MyService extends Service {

    ....

    @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()停止服务。谷歌专门提供了一个IntentService类来简化程序员的工作

二.关于IntentService与源码分析

Google 为方便开发者使用,提高开发效率,封装了 IntentService 和 HandlerThread。HandlerThread 继承自 Thread,内部封装了 Looper。那 IntentService 呢? 首先我们来,阅读IntentService 的源码:
public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

 public IntentService(String name) {
        super();
        mName = name;
    }

   public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

@Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

 @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

   public stract void onHandleIntent(@Nullable Intent intent);
}

我们先观察onCreate方法,开启一个HandlerThread线程,HandlerThread与普通Thread的区别在于,HandlerThread内部开启了自己的Looper 循环,可以通过获取其Looper往他的消息队列发消息。然后在实例化了一个ServiceHandler对象,构造方法传入了HandlerThread对象的Looper循环器。我们再来观察onStart 方法,通过obtainMessage方法构造消息并入队HandlerThread对象的消息队列,我们再来看ServiceHandler对消息的处理handleMessage方法,其实就是调用IntentService 子类的onHandleIntent方法。这样我们在子类onHandleIntent方法中实现耗时业务操作最终会在子线程中执行。

三.实现我们的IntentService

public class MyIntentService extends IntentService {
    private boolean isRunning;
    LocalBroadcastManager mLocalBroadcastManager ;

    @Override
    public void onCreate() {
        super.onCreate();
        //注册广播
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
    }


    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        try {
            isRunning = true;
            int progress = 0;
            while (isRunning){
                Thread.sleep(100);
                progress++;
                if(progress==100){
                    isRunning = false;
                }
                sendThreadStatus("Runing........",progress);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /**
     * 发送进度消息
     */
    private void sendThreadStatus(String status, int progress) {
        Intent intent = new Intent(IntentServiceActivity.ACTION_TYPE_THREAD);
        intent.putExtra("status", status);
        intent.putExtra("progress", progress);
        mLocalBroadcastManager.sendBroadcast(intent);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

Activity的处理

public class IntentServiceActivity extends Activity {
    ProgressBar progressbar;
    TextView tv_progress;
    public static String ACTION_TYPE_THREAD = "ACTION_TYPE_THREAD";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        progressbar = findViewById(R.id.progressbar);
        tv_progress = findViewById(R.id.tv_progress);
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyBroadcastReceiver receiver = new MyBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_TYPE_THREAD);
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
        manager.registerReceiver(receiver,filter);
        Intent i = new Intent(IntentServiceActivity.this, MyIntentService.class);
          startService(i);
    }

    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(ACTION_TYPE_THREAD.equals(intent.getAction())){
                //更改UI
                int progress = intent.getIntExtra("progress", 0);
                progressbar.setProgress(progress);
                tv_progress.setText(progress + "%");
            }
        }
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_progress"
        android:layout_width="40dp"
        android:layout_height="20dp" />

    <ProgressBar
        android:max="100"
        android:progress="50"
        android:secondaryProgress="80"
        android:id="@+id/progressbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

在这里,我们模拟的时候一个后台更新的下载进度条,效果如下
在这里插入图片描述

后话

启动IntentService的方式,我们并不建议通过bindService() 启动 IntentService。原因很简单,查看源码,onBind方法默认返回null,,如果你执意要 bindService() 来启动 IntentService,那么 onHandleIntent() 不会被回调,相当于在你使用 Service
@Override
@Nullable
public IBinder onBind(Intent intent) {
    return null;
}

附上代码下载地址

 

作者:王宗耀 欢迎转载,与人分享是进步的源泉!
  转载请保留原文地址:http://blog.csdn.net/wzy901213

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值