天天看點

Android學習小Demo(19)利用Loader來實時接收短信

之前寫過一篇文章《》,在裡面利用ContentOberver去監測短信URI内容的變化。我們先來回顧一下,是如何利用ContentOberver來監測短信内容的變化的。

1)要自定義一個類,比如SmsContentObserver,繼承ContentObserver,并且實作其onChange方法。

2)在onChange方法中去查詢對應Uri,比如短信收件箱的内容,并将對應的記錄利用Handler發送到主界面。

3)在主界面Activity中,要建立一個SmsContentObserver,并且将其注冊到ContentReslover中去。

4)在主界面Activity的Handler中獲得在SmsContentObserver中變化的消息,更新主界面。

總的來說,過程就大概是這樣,大家有興趣可以看一下這一篇文章。

而本文介紹的是另外一種方法,利用Loader來實作差不多的效果,既然能夠說效果差不多,那麼就說明了Loader有一個跟ContentObserver的特性,沒錯,它能夠檢測到對應内容的變化。

先簡單說一下什麼是Loader。

Loader是Android在3.0之後才引進的一個類,其主要目的在于讓Android跟Data之間的互動變得更加簡單和高效,概括起來,我覺得其功能有以下兩點:

1)動态監測所處理對象狀态的變化,大部分情況下是處理資料,但我覺得隻是一方面。

2)當界面變化,需要被重新建立的時候,它們能夠重新load到上一次的資料,而不需要再重新進行查詢。

當然,它還是異步的,也就意味着不會阻塞到主界面的顯示,不過這個功能很多其他的輔助類都有,也就不算啥特點了。

而正是到其第一點的特性,才讓我們有機會可以不用那麼麻煩去實作一個ContentObserver,而轉而來利用Loader來實作相同的功能。

這一次我們做一個展示短信的Demo。當我們打開手機中的短信應用的時候,如果這個時候有新短信進來,我們會看到新短信馬上就顯示在界面上的,而我們這個Demo也正是如此效果,具體請看(截圖大了點,莫怪)。

Android學習小Demo(19)利用Loader來實時接收短信

從上圖中可以看到,當我們點選Send按鈕的時候,短信發過去,ListView中馬上就顯示出來剛剛發送的短信。

那麼應該怎麼使用Loader呢,我們下面來看代碼吧。

1)由于Loader是3.0之後才引進來的,是以在3.0之前,如果我們想要使用Loader的時候,主Activity必須要繼承FragmentActivity,才能夠拿到LoaderManager。

2)要實作LoaderManager的内部接口LoaderCallbacks<D>,這是一個泛型接口,其定義如下:

是以,我們代碼中的第一步就是要實作這個接口,如下:

3)要定義一個Uri,因為Loader它必須要從某個地方load資料,而這個Demo中,我們要擷取的是收件箱的短信,是以在這裡就是拿sms/inbox了。

4)在OnCreateLoader方法中,要建立一個CursorLoader。CursorLoader是AsyncTaskLoader的一個子類,是以它是一個異步的Loader,不會影響到主界面的展示。

5)在OnLoadFinished方法中,對Load完回來存放在cursor的資料進行處理。

上面的接口,隻是實作的方式而已,而當調用下面這個方法的時候,Loader才開始真正地發揮作用。在onCreate方法中,

由于我們是用的support包,是以需要用getSupportLoaderManager類來調用initLoader方法,此方法有三個參數:

a)id,由于一個Activity或者Fragment隻有一個LoaderManager,但是一個LoaderManager可以有多個Loader,用來處理不同的資料,是以id在這裡能唯一地确定是哪個Loader。

b)bundle,這是傳給LoaderManager的參數集合。

c)這是一個LoaderCallbacks的實作類,在這個Demo中,就是此Activity,是以就是this。

6)當調用getSupportLoaderManager().initLoader()方法的時候,Android首先會根據 id 去判斷是否已經存在這樣的一個loader了,如果存在的話,它就會直接使用已有的loader,而不會去建立一個新的,也就是說,它不會去調用接口方法中的onCreateLoader方法了。而如果不存在對應 id 的Loader,則會去調用onCreateLoader方法,并執行個體化一個新的Loader出來。

而當對應 id 的loader已經存在的時候,Android會直接load資料,而接口方法中的onLoadFinished也會在資料load完之後馬上被調用,這樣就會存在一種情況,如果在onLoadFinished方法中使用的變量是在onCreateLoader中才初始化的,那麼這個變量根本都沒被初始化,就被使用了,程式就會報錯了,是以在實際開發中,要考慮到這樣一種情況的存在,在 onLoadFinished方法中,要做好一些判斷。

最後還有一個onLoaderReset方法,沒有被用到,這個方法主要是在Loader不再被使用的時候,被關閉了等情況下,用來釋放對Loader的使用的,比如在這個Demo中,如果loader不再用了,那麼我們的Adpater就不應該再關聯對應的cursor了,那麼就可以在這裡進行判斷。

結束!