1. 程式人生 > >Android圖片編輯器實踐指南-2.圖片視訊選擇器(1)

Android圖片編輯器實踐指南-2.圖片視訊選擇器(1)

本篇將會介紹媒體選擇器,包括圖片選擇器和視訊選擇器,更進一步的擴充套件到根據目錄顯示不同的圖片。

2.1 圖片選擇器

具體開發圖片選擇器之前,先說明一下MediaStore類,之後所有的圖片操作,查詢都和這個類有關係。官網上對這個類的定義為:

The Media provider contains meta data for all available media on both internal and external storage devices.

簡單理解就是對外提供裝置上所有的媒體,它在android的包目錄為:

package android.provider;

這個類屬於provider,即ContentProvider元件之一,對外提供介面查詢自身的資料。MediaStore這個類就是android系統提供的一個多媒體資料庫類,這個類包括了多媒體資料庫的所有資訊,包括音訊,視訊和影象。因此使用者直接利用ContentResolver呼叫相關的query方法去獲取相關資料。在這個類中定義了較多的內部類,檢視官網的API介面可看出包含MediaStore.Audio、MediaStore.Video、MediaStore.Images、MediaStore.Files4個內部類;同時包含了一個介面MediaStore.MediaColumes,該介面定義了所有與媒體相關的資料庫標都會用到的資料庫欄位。見圖1:

在這裡插入圖片描述圖1:MediaStore類的結構圖

圖1顯示了MediaStore類的結構圖,包含了相關的內部類和MediaColumns介面,這裡展開了Images內部類。Images類定義了一個名為ImageColumns的介面,該介面定義了單獨針對Image的資料庫欄位。同時Images類定義類一個名為Media的內部類用於查詢和Image相關的資訊,此外還定義了一個名為Thumbnails的內部類用於查詢和Image相關的縮圖的資訊。

下面來看Image.Media的query函式,其程式碼非常簡單,如下所示: code 1:Image.Media query函式 code 1:Image.Media query函式

說明:可見Image.Media的query函式直接呼叫ContentResolver的query函式

ContentResolver的query函式分析如下code 2: 在這裡插入圖片描述 code 2:ContentResolver query函式

說明:

  • uri:指明要查詢的資料庫名稱加上表的名稱,從MediaStore類中可以找到相應資訊的引數
  • projection:指定查詢資料庫表中的哪幾列
  • selection:指定查詢條件
  • selectionArgs:引數selection裡有 ?這個符號是,這裡可以以實際值代替這個問號。如果selection這個沒有?的話,那麼這個String陣列可以為null。
  • sortOrder:指定查詢結果的排列順序

接下來新建一個包component存放基礎的元件,在component裡新建一個類MediaChooseComponent。這裡思考一下,既然作為一個元件,那麼必然是提供所有上層業務所使用的,那麼這個類也就存在唯一的例項,因此這個類要設計成單例類。這裡詳細說明一下單例設計模式。

設計模式-單例

定義:一個類有且僅有一個例項,並且自行例項化向整個系統提供

在app整個生命週期中,往往需要唯一的一個類的例項,那麼就應該使用單例模式,因此就類似上文中MediaChooseComponent,具體實現方式有如下幾點:

  • 將類的構造方法私有化,使其不能在類的外部通過new來例項化物件
  • 在該類內部定義一個該類的static物件,宣告private型別
  • 定義一個靜態方法返回這個唯一的物件

實現方法分為餓漢模式,懶漢模式,雙重判空

餓漢模式

直接定義並初始化static宣告的變數,優點是不存線上程安全問題,缺點是不管你具體用不用這個類,它都會被載入到記憶體中,如下code3: 在這裡插入圖片描述 code 3:單例—餓漢模式

懶漢模式

延遲初始化,在需要的時候初始化,存在多執行緒安全問題,因為Java物件的建立過程不是原子操作,分為好幾個步驟,具體可參看Java虛擬機器,因此當多個執行緒同時訪問的時候,就會出現執行緒安全問題,例如執行緒1判斷instance == null,執行例項化過程;這個時候例項化還沒完成,執行緒2同時也判斷,此時instance==null 為true,因此也會去例項化物件,就會例項化2個物件出來。如下code4: 在這裡插入圖片描述 code 4:單例—懶漢模式

雙重判空

如下code5,首先判斷為空,然後加了鎖,再判斷下是否為空,如果為空則例項化物件。 在這裡插入圖片描述 code 5:單例—雙重判空

說明:這裡使用了final和volatile關鍵字,final關鍵字在修飾類的時候,該類不可被繼承,因此不會被繼承它的類所改變行為;volatile關鍵字修飾變數的時候表明該變數是對多執行緒可見的,滿足一致性,即各個執行緒的工作記憶體能立即發現該變數的改變並保證一致性。

單例模式還有一些其他的實現方案,比如用列舉之類的,就不一一說明了,以上是最基礎的實現方法。

現在來修改MediaChooseComponent為如下:首先定義了一個volatile static變數,通過getIns獲取,在私有構造方法中初始化mediaResolver;定義了imageMediasCache作為image的快取,同時定義了2個介面OnMediaChangeListener和OnMediaDirChangListener。從命名可看出是在Media發生改變或者MediaDir發生改變的時候發出通知,這裡先忽略Dir相關的邏輯。

在這裡插入圖片描述 接下來就是獲取Image的核心函式,在loadImageMedias方法中使用一個執行緒非同步查詢image media;在具體查詢過程中,使用ContentResolve結合MediaStore最後生成MediaItem型別的物件加入到ArrayList中,最終得到需要到image資料。finally裡面要close cursor。 在這裡插入圖片描述 總結 此篇初步介紹了MediaStore基礎,並結合MediaChooseComponent元件詳細介紹了單例設計模式,最終我們通過非同步呼叫queryImageList()獲取所有到Image media,並最終存放在陣列中。下一篇將會完整實現圖片選擇器,並加入按照目錄選取功能。

更多精彩技術分享請掃碼關注小碼時間(XiaoMaTime)

在這裡插入圖片描述