Android之IntentService使用

Android之IntentService使用

文章链接:http://blog.csdn.net/qq_16628781/article/details/67110657
知识点:
  1. IntentService简介;
  2. Thread/Runnable/service开启线程;
  3. IntentService使用;
  4. IntentService源码简析和使用场景;
  5. 新名词记录{onHandleIntent();START_REDELIVER_INTENT;START_NOT_STICKY;消息队列:Looper,Handler等;}

概述

说到线程,大家一定是想到利Thread和Runnable了,因为他们使我们新开线程最常用到的方式了。但是实话实话,线程如果理解不透彻,是很难进行管理的。万一没弄好,那么就有可能造成问题。

同样,我们也可以在service进行耗时操作,但是但是,在service里面还是需要进行新开线程来操作的。在onStartCommand()方法里面进行新开线程。

但是有木有一种更加简单的办法进行耗时操作呢,不需要我们去new一条子线程,也不需要去管理子线程。答案是肯定的。

Android中给我们封装了service成IntentService给我们直接使用,它的好处有两点:1、不用我们手动去new一个子线程;2、不用我们去管理子线程,当任务执行完之后,IntentService会自动停止线程。


通用new新线程方式1
Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //开启线程做耗时操作
            }
        });
        thread.start();

通用new新线程方式2

在service的onStartCommand()方法中操作

@Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                // 此处进行耗时的操作
            }  
        }).start();  
        return START_STICKY;  
    } 

IntentService执行耗时操作

IntentServiceImpl继承IntentService,并实现一个需要传入工作线程名字的构造函数和onHandleIntent(Intent intent)方法。

我们具体来说下onHandleIntent(Intent intent)方法:此方法是用来实现耗时操作的回调,你可以在这里进行访问网络,io读存和其它耗时操作。参数Intent就是你调用startService(intent)里面传入的原始的intent。我在下面分别传入了3个参数,模拟进行3中不同的操作,只是让线程停止4秒钟,模拟耗时操作。然后我们就可以利用广播进行数据传递,或者将下载的内容放入本地sdcard等等。

/**
 * desc:
 * <p>
 * author:kuyu.yaojt (tanksu)
 * <p>
 * email:yaojt@kuyumall.com
 * <p>
 * blog:http://blog.csdn.net/qq_16628781
 * <p>
 * date:17/3/27
 */

public class IntentServiceImpl extends IntentService {


    /**
     *
     */
    public IntentServiceImpl() {
        super("intentServiceImpl");
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentServiceImpl(String name, Handler handler) {
        //传入名字,标记工作线程,主要是为了调试用。
        super(name);
        this.mHandler = handler;
    }

    private Handler mHandler;

    @Override
    protected void onHandleIntent(Intent intent) {
        //根据Intent的不同进行不同的事务处理
        System.out.println("onHandleIntent----->");
        String id = intent.getExtras().getString("requestid");
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String resule = "";
        switch (id) {
            case "t1":
                resule = "结束t1工作";
                break;
            case "t2":
                resule = "结束t2工作";
                break;
            case "t3":
                resule = "结束t3工作";
                break;
        }

    }

接下来是如何启动。

public void initView() {
        Intent intent = new Intent(this, IntentServiceImpl.class);
        intent.putExtra("requestid", "t1");
        startService(intent);

        Intent intent2 = new Intent(this, IntentServiceImpl.class);
        intent.putExtra("requestid", "t2");
        startService(intent);

        Intent intent3 = new Intent(this, IntentServiceImpl.class);
        intent.putExtra("requestid", "t3");
        startService(intent);
    }

上面代码,我们一共启动了3次,执行3个耗时的操作,但是在onHandleIntent()方法里面,并不会一起执行全部的请求,而是一个一个顺序执行,这一点尤其需要注意。

因为IntentService是继承自Service,所以也是需要在manifest文件中声明的。

<service android:name=".sdk.java.network.IntentServiceImpl">
            <intent-filter>
                <action android:name="con.yaojt.intentservice" />
            </intent-filter>
        </service>

以上就是IntentService的使用方法。下面我们将去看看他的源码,源码其实不多,大概浏览下它是怎么实现的,还有就是有神马用处?

下面的类就是IntentService的实现类,下面总的说几点(从上往下):
1. IntentService新开的线程都有自己的消息队列;
2. 在消息队列最后会回调onHandleIntent()方法;
3. 构造方法传入的name是用来区分线程和调试作用,不重要;
4. onCreate()中会为此线程得到消息队列,并构建处理的handler;
5. onStartCommand()不推荐重写。除非你需要像是向后台轮询的操作,就需要重写(详见方法中的解释);
6. 一次处理一个请求,之后挂起实例内的其它请求;

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); //设置looper
            }

            @Override
            public void handleMessage(Message msg) {
                onHandleIntent((Intent) msg.obj); //回调onHandleIntent()方法给用户自行处理
                stopSelf(msg.arg1);
            }
        }

        public IntentService(String name) {
            super();
            mName = name; //名字只是来标记此线程,调试用
        }

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

        @Override
        public void onCreate() {
            // TODO: It would be nice to have an option to hold a partial wakelock
            // during processing, and to have a static startService(Context, Intent)
            // method that would launch the service & hand off a wakelock.

            super.onCreate();
            HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");//根据传入的name,创建一个线程
            thread.start();//这个方法还是需要调用的

            mServiceLooper = thread.getLooper(); //得到此线程的一个looper,让他来循环此线程
            mServiceHandler = new ServiceHandler(mServiceLooper); //得到一个处理intent的handler
        }

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

        //这个方法系统是不推荐重写的。但是要重写onHandleIntent()抽象方法,因为系统拿到一个请求之后,就会调用此方法
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            onStart(intent, startId); //这里会给实现的ServiceHandler发送一个消息,然后在handleMessage()里面进行调用onHandleIntent()方法
            //START_REDELIVER_INTENT:当服务开始后,被系统杀掉了,就会重新启动,并且将最后的一个intent重新分发给onStartCommand()方法
            //除非用户掉用了stopself()方法,否则会一直重新分发最后一个intent。如果传入的是一个null的intent,那么将不会调用此方法。

            //START_NOT_STICKY:当服务没杀掉之后,不会重新启动,也不会传递intent,除非再次调用startService()方法。
            //我们这里可以做一个向后台轮询数据的工作,在我们启动intentservice之后,如果onStartCommand()返回这个类型,
            //那么这儿服务不会再启动,这样就可以避免内存不足时,我们的线程被杀掉。然后我们又可以在onStartCommand()里头,
            //设置一个"闹钟"在多少分钟之后,再次调用
            //startService()启动此服务,然后在onStartCommand()做一个询问后台的网络请求,因为此服务仅此一次,所以不担心被杀掉
            //如此反复,那么就是一个完整的轮询工作流程了
            return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
        }

        @Override
        public void onDestroy() {
            mServiceLooper.quit(); //停止线程的消息轮询
        }

        @Override
        @Nullable
        public IBinder onBind(Intent intent) {
            return null; //在你需要为你的服务进行绑定的时候,才需要返回IBinder对象
        }

        //工作线程中有了请求之后,就会调用。一次只会异步处理一个intent请求,在此对象中需要启动的其它请求只能等待,
        //而不会挂起其它IntentService的对象。当所有的请求都处理完之后,它会自动的停止自身。而不用手动去调用stopSelf()方法
        //startService(Intent)启动IntentService
        @WorkerThread
        protected abstract void onHandleIntent(@Nullable Intent intent);
    }

总结

IntentService是一个很好用的类,比如我们需要向后台传输n张图片,就可以使用这一个类,开启执行之后哦,我们就可以不用管它,等完成之后,会自己杀掉自己。省去了很多的操作步骤。

onStartCommand()的返回参数也是有很多的作用,SDK中说的就是用来向后台进行轮询操作。START_REDELIVER_INTENT和START_NOT_STICKY的作用需要好好理解才能够更好的使用此类。

如有任何问题,请及时与我联系。谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值