android IntentService的深入理解

什么是IntentService?

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through android.content.Context.startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work. 

This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate. 

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

意思是说:IntentService是一个通过 Context.startService(Intent) 启动可以处理异步请求的Service,使用时你只需要继承IntentService和重写其中的 onHandleIntent(Intent) 方法接收一个Intent对象,当线程执行完毕会停止自己(一般在工作完成的时候). 所有的请求的处理都在一个工作线程中完成,它们会交替执行(但不会阻塞主线程的执行),一次只能执行一个请求.

下面我们看下源代码是怎么实现的

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;//这是Looper
    private volatile ServiceHandler mServiceHandler;//这是Handler
    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);//hook钩子函数
            stopSelf(msg.arg1);
        }
    }


    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentService(String name) {
        super();
        mName = name;
    }


    /**
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     *
     */
    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 + "]");//这里我们创建了一个HandlerThread,意思是创建了一个        //线程
        thread.start();
        mServiceLooper = thread.getLooper();//这里的Looper对象时从线程中拿到的,这和主线程的Looper是不一样的
        mServiceHandler = new ServiceHandler(mServiceLooper);//把Looper对象配置到Handler,说明这个Looper循环的是子线程HandlerThread 中的消息,所以mServiceHandler 发送的消息HandlerThread会处理的
    }


    @Override
    public void onStart(Intent intent, int startId) {                                                                                       //这里是UI主线程,发送消息,等于主线程向子线程发送了一个消息。
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }


    /**
     * You should not override this method for your IntentService. Instead,
     * override {@link #onHandleIntent}, which the system calls when the IntentService
     * receives a start request.
     * @see android.app.Service#onStartCommand
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }


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


    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null. 
     * @see android.app.Service#onBind
     */
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     */
    protected abstract void onHandleIntent(Intent intent);
}
HandlerThread是什么呢

源代码:

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 */
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }

    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread 
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    
    /**
     * Ask the currently running looper to quit.  If the thread has not
     * been started or has finished (that is if {@link #getLooper} returns
     * null), then false is returned.  Otherwise the looper is asked to
     * quit and true is returned.
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
    
    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

HandlerThread就是一个线程,而且是一个LooperThread,这个Looper我们可以创建Handler对象,Thread的start()方法必须被执行。

有了looper就可以消息查询了。
针对IntentService的用法我们举例说明:

MainAcitivity中

</pre><pre name="code" class="java">@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Log.d("intent", "MainActivity.onCreate");
		count++;
		startService(count);
		LinearLayout layoutg = (LinearLayout) findViewById(R.id.rootview);
		layoutg.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				count++;
				startService(count);
			}
		});
	}
	
	public void startService(int flag){
		Intent service = new Intent(MainActivity.this,MyIntentService.class);
		service.putExtra("flag", flag);
		startService(service);
	}

MyIntenteService代码

public class MyIntentService extends IntentService {

	
	
	public MyIntentService() {
		super("myIntentService");
		Log.d("intent", "MyIntentService----name:myIntentService");
	}


	@Override
	public void onCreate() {
		Log.d("intent", "MyIntentService----onCreate");
		super.onCreate();
	}


	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub
		Log.d("intent", "MyIntentService----flag:"+intent.getIntExtra("flag", 0));
		try {
			Log.d("intent", "MyIntentService----task running");
			int count = 0;
			while(count<5){
				count++;
				Log.d("intent", "MyIntentService----"+count);
				TimeUnit.SECONDS.sleep(1);
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	@Override
	public void onDestroy() {
		Log.d("intent", "MyIntentService----onDestroy");
		super.onDestroy();
	}
	
	
}

main_layout.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    tools:context="com.example.heraracky.MainActivity"
    tools:ignore="MergeRootFrame" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/rootview"
        android:orientation="vertical"
        android:background="@android:color/darker_gray">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"/>
        <TextView
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:text="textView"/>
    </LinearLayout>
</FrameLayout>


这时候我们点击下linearlayout的触发事件,flag为2,在task running执行的时候,在点击一次linearlayout的触发事件,看运行结果


小结:

flag为1时,HandlerThread执行完毕后,intentService就自己onDestroy了;flag为2时,当HandlerThread还未执行完毕时,有发送一次intent,这时flag为3,但是并没有立即执行,而是等到flag为2的线程执行完成后,才继续执行flag为3的请求,执行完成后才调用service的onDestroy方法。

这样就不用我们自己来控制Service的生命周期了。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值