Android專案篇(二):開源庫及工具的封裝
TicktockMusic 音樂播放器專案相關文章彙總:
- Clean Architecture 架構:https://www.jianshu.com/p/15ea0fecb61d
- 開源庫封裝:https://www.jianshu.com/p/1645b81dc994
- 自定義播放暫停按鈕:https://www.jianshu.com/p/74f38e9b16fc
- 自定義歌詞控制元件:https://www.jianshu.com/p/ab735509cc74
在我們的專案中,總會不可避免的用到三方的開源專案。在開源庫的選擇上,我們一般會選擇成熟穩定,不斷更新,作者及時解決 issue 的專案。而且大部分開源專案開放的 api 已經非常方便,使用簡單,容易入手。但是,在我們做專案的過程中,最好再將開源專案進行封裝。本文以圖片載入框架和工具的封裝為例來討論下封裝的好處。
必要性
1、統一入口,邏輯改動方便。
2、若三方庫停止維護或者業務不滿足需求需要更換三方庫時,封裝後方便改動。
圖片載入框架的封裝
Android 專案中常用的圖片載入框架基本上都是 Picasso、Glide、Fresco、android-universal-image-loader,就近年來說,Picasso 和 Glide 由於其便捷性,更為受歡迎。本文就介紹下 Glide 的封裝。
首先,最簡單的封裝如下:
public class ImageLoader {
public static void display(Context context, String imageUrl, ImageView imageView) {
Glide.with(context).load(imageUrl).into(imageView);
}
}
其實這樣已經可以應對一般的場景了,但是業務相對複雜的話,比如改變圖片的快取策略、僅在wifi下載入圖片、圖片圓角等,這種簡單的封裝就無法滿足了。 接下來我們採用策略模式進行封裝。
1、 建立基礎策略介面,所有的策略均實現此介面
public interface IBaseImageStrategy {
void display(Context context, ImageConfig imageConfig);
void clean(Context context, ImageView imageView);
}
2、 圖片載入配置類,此類包含用到的圖片載入引數,採用 Build 模式進行引數的配置,這樣使用更加靈活。
public class ImageConfig {
private Object url;
private ImageView imageView;
...
public ImageConfig(Builder builder) {
this.url = builder.url;
this.imageView = builder.imageView;
...
}
... //getter and setter
public static class Builder {
private Object url;
private ImageView imageView;
...
public ImageConfig build() {
return new ImageConfig(this);
}
}
}
3、具體的策略,比如我們採用 Glide ,則建立 GlideImageLoaderStrategy,可以根據 config 的屬性作為引數,來配置 Glide 具體的載入引數。
public class GlideImageLoaderStrategy implements IBaseImageStrategy {
@Override
public void display(Context context, ImageConfig imageConfig) {
RequestOptions options = getOptions(context, imageConfig);
Object url = getPath(imageConfig);
if (!imageConfig.isAsBitmap()) {
RequestBuilder<Drawable> requestBuilder = Glide.with(context)
.load(url)
.apply(options);
if (!imageConfig.isRound() && imageConfig.getDuration() != 0) {
requestBuilder = requestBuilder.transition(new DrawableTransitionOptions()
.crossFade(imageConfig.getDuration()));
}
requestBuilder.into(imageConfig.getImageView());
} else {
RequestBuilder<Bitmap> requestBuilder = Glide.with(context)
.asBitmap()
.load(url)
.apply(options);
if (!imageConfig.isRound() && imageConfig.getDuration() != 0) {
requestBuilder = requestBuilder.transition(new BitmapTransitionOptions()
.crossFade(imageConfig.getDuration()));
}
requestBuilder.into(imageConfig.getTarget());
}
}
/**
* Glide 配置
*
* @param context context
* @param imageConfig 配置
* @return Glide配置
*/
private RequestOptions getOptions(Context context, ImageConfig imageConfig) {
RequestOptions options = new RequestOptions()
.placeholder(imageConfig.getDefaultRes())
.error(imageConfig.getErrorRes());
...
return options;
}
@Override
public void clean(Context context, ImageView imageView) {
Glide.with(context).clear(imageView);
}
4、統一入口,此處採用單例模式。
public class ImageLoader implements IBaseImageStrategy {
private static ImageLoader INSTANCE;
private IBaseImageStrategy mImageStrategy;
private ImageLoader(){
mImageStrategy = new GlideImageLoaderStrategy();
}
public static ImageLoader getInstance() {
if (INSTANCE == null) {
synchronized (ImageLoader.class) {
if (INSTANCE == null) {
INSTANCE = new ImageLoader();
}
}
}
return INSTANCE;
}
@Override
public void display(Context context, ImageConfig imageConfig) {
mImageStrategy.display(context, imageConfig);
}
@Override
public void clean(Context context, ImageView imageView) {
mImageStrategy.clean(context, imageView);
}
}
5、使用,所有的載入均使用統一的 ImageLoader 進行載入。
ImageLoader.getInstance().display(context, new ImageConfig.Builder()
.url(url)
.placeholder(R.drawable.ic_placeholder)
.into(imageView)
.build());
6、當我們因為一些原因需要切換圖片載入庫,比如之前用的 Picasso(策略類為 PicassoImageLoaderStrategy),由於要載入 gif 圖片,所以切換到 Glide,這樣我們只用新建一個 GlideImageLoaderStrategy,在 ImageLoader 中改變 IBaseImageStrategy 的例項類即可切換。
圖片載入框架封裝總結
綜上,這種封裝模式的好處就是便於根據業務及其他需求進行擴充套件和維護。當然封裝並不是萬能的,比如使用 Glide 可能用到的 Target ,在 Picasso 中並沒有此類,所以用到 Target 的地方我們仍然需要一個個手動的更改。另外,Fresco 由於使用時涉及 xml 檔案等,用法相對特殊,所以使用 Fresco 的話,封裝很難顧及到。本文的封裝主要是提供思路,以一種相對維護性高的方式進行封裝。
工具的封裝
上邊以 Glide 為例介紹了開源專案的封裝。我們在專案過程中,也會用到各種工具,接下來介紹下 SharedPrefrences 的封裝。 SharedPrefrences 經常用來儲存一些簡單的資訊,如各種狀態,部分快取等。由於其特殊性,所以很多人會寫一個工具類來簡單處理下 SharedPrefrences 的使用,但是 SharedPrefrences 作為一種資料儲存的手段,我覺得還是需要重視起來,以便處理後續的需求。接下來就介紹下 SharedPrefrences 的封裝。
1、定義資料倉儲的介面,所有的資料倉儲介面都繼承此介面,並且建立此介面的實現類。
資料倉儲介面:
public interface DataRepo {
void put(String key, String value);
void put(String key, int value);
void put(String key, boolean value);
void put(String key, long value);
String getString(String key);
String getString(String key, String defaultValue);
int getInt(String key);
int getInt(String key, int defaultValue);
long getLong(String key);
boolean getBoolean(String key);
boolean getBoolean(String key, boolean defaultValue);
void remove(String key);
Map<String, ?> getAll();
boolean contains(String key);
void clear();
}
實現類:
public class SharedPreferenceDataRepo implements DataRepo {
private final SharedPreferences mSharedPreferences;
public SharedPreferenceDataRepo(Context context, String fileName, int mode) {
mSharedPreferences = context.getSharedPreferences(fileName, mode);
}
@Override
public void put(String key, String value) {
mSharedPreferences.edit().putString(key, value).commit();
}
...
@Override
public void clear() {
mSharedPreferences.edit().clear().commit();
}
}
2、定義具體的倉庫介面,如 CacheRepo,並建立此介面的實現類。
倉庫介面:
public interface CacheRepo extends DataRepo{
void setCache(String key, String value);
String getCache(String key);
}
實現類:
public class CacheRepoImpl extends SharedPreferenceDataRepo implements CacheRepo {
private static final String FILE_NAME = "cache_sp";
public CacheRepoImpl(Context context) {
super(context, FILE_NAME, Context.MODE_PRIVATE);
}
@Override
public void setCache(String key, String value) {
put(key, value);
}
@Override
public String getCache(String key) {
return getString(key);
}
}
3、統一入口,這裡類似一個工廠方法,根據需要來獲取不同的資料倉儲。
public class DataManager {
private final CacheRepo mCacheRepo;
private final ConfigRepo mConfigRepo;
private volatile static DataManager INSTANCE;
private DataManager(Context context) {
mCacheRepo = new CacheRepoImpl(context);
mConfigRepo = new ConfigRepoImpl(context);
}
public static DataManager getInstance(Context context) {
if (INSTANCE == null) {
synchronized (DataManager.class) {
if (INSTANCE == null) {
INSTANCE = new DataManager(context);
}
}
}
return INSTANCE;
}
public CacheRepo getCacheRepo() {
return mCacheRepo;
}
public ConfigRepo getConfigRepo() {
return mConfigRepo;
}
}
使用,統一通過 DataManager 進行載入:
DataManager.getInstance(mContext).getCacheRepo().getCache("key");
SharedPrefrences 封裝總結
SharedPrefrences 的封裝和 Glide 類似,其實也都是為了提高可維護性。由於 SharedPrefrences 可以作為資料儲存的一種方式,所以為了方便的改變儲存方式,我覺得有必要封裝一下的。舉個例子,假如我們專案一開始利用 SharedPrefrences 快取使用者的一些資訊,但是隨著業務逐漸複雜起來,需要快取的使用者資訊逐漸增多,或者需要快取多個使用者的資訊,並且支援一些快取資料的增刪改查,這再繼續使用 SharedPrefrences 就不太合適了,採用資料庫比較合適。利用簡單封裝的工具類修改的話,可能每個使用到的地方都需要手動的更改使用方法,但是通過上述的封裝,我們可以很方便的轉化為資料庫的儲存方式,這樣維護起來就比較方便了。
總結
對於封裝,也要考慮開源專案的本身因素,假如侵入性比較強或者作者更新及時、專案比較複雜之類的,也可以根據人力考慮是否封裝及如何封裝。
本文以 Glide 和 SharedPrefrences 為例分別介紹了開源專案和工具的封裝,封裝的好處是為了提高程式碼的可維護性和擴充套件性等,以便應付不斷變化的需求及其他因素。所有的程式碼都在 TicktockMusic 中,歡迎討論。
相關文章
- 最新Android開源庫、工具、開源專案整理分享Android
- 基於 uber 開源的 zap 二次封裝封裝
- Android常用工具類的封裝Android封裝
- aardio封裝庫) 微軟開源的js引擎(ChakraCore)封裝微軟JS
- Android專案中最火最常用的優秀開源專案Android
- vue專案封裝iconVue封裝
- ToolBar專案封裝使用封裝
- Vue管理系統前端系列二相關工具引入及封裝Vue前端封裝
- 基於 Multitype 開源庫封裝更好用的RecyclerView.Adapter封裝ViewAPT
- 一次Android動畫工具類的封裝Android動畫封裝
- 開發自己的工具庫(一):專案搭建
- 開源專案audioFlux: 針對音訊領域的深度學習工具庫UX音訊深度學習
- vue-axios的總結及專案中的常見封裝方法。VueiOS封裝
- aardio封裝庫) sunny抓包工具的使用封裝
- Android 圖表開源庫調研及使用示例Android
- Android 封裝AsyncTask操作Sqlite資料庫Android封裝SQLite資料庫
- 封裝C專案為dll封裝
- 關於TornadoFx和Android的全域性配置工具類封裝實現及思路解析Android封裝
- GitHub 上適合新手的開源專案(Python 篇)GithubPython
- Android開源庫的製作Android
- 實用的Android開源庫Android
- Android開源mvp專案,實現玩Android客戶端AndroidMVP客戶端
- JavaFx 生成二維碼工具類封裝Java封裝
- 專案常用JS方法封裝(二) [ 時間相關處理 ]JS封裝
- 「實戰篇」開源專案docker化運維部署-原始碼介紹(二)Docker運維原始碼
- 開源電子書專案FBReader初探(二)
- IOS技術分享| ARCallPlus 開源專案(二)iOS
- Android 解讀開源專案UniversalMusicPlayer(資料管理)Android
- Android 解讀開源專案UniversalMusicPlayer(播放控制層)Android
- 在RN專案上對axios的封裝iOS封裝
- vue專案的網路模組封裝Vue封裝
- 常用的幾個提高iOS開發效率的開源類庫及工具iOS
- Android播放器基礎封裝庫PlayerBaseAndroid播放器封裝
- GitHub 專案 README 展示使用本開源庫的 AppGithubAPP
- Android 面試開源框架篇Android面試框架
- Android 談談封裝那些事 –BaseActivity 和 BaseFragment(二)Android封裝Fragment
- 完全使用 Docker 開發 PHP 專案 (二): 配置篇DockerPHP
- 基於Docker封裝的開發包工具Docker封裝