国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

詳解Android ViewCompat的作用

2019-10-22 18:33:01
字體:
來源:轉載
供稿:網友

詳解Android ViewCompat的作用

ViewCompat類主要是用來提供兼容性的, 比如我最近看的比較的多的canScrollVertically方法, 在ViewCompat里面針對幾個版本有不同的實現, 原理上還是根據版本判斷, 有時甚至還要判斷傳入參數的類型. 但是要注意的是, ViewCompat僅僅讓你調用不崩潰, 并不保證你調用的結果在不同版本的機器上一致.

關于如何優雅的組織代碼, ViewCompat類的結構非常適合我們參考.

ViewCompat里面定義了一個接口, 這個接口列出了所有它支持的方法

interface ViewCompatImpl {    public boolean canScrollHorizontally(View v, int direction);    public boolean canScrollVertically(View v, int direction);    public int getOverScrollMode(View v);    public void setOverScrollMode(View v, int mode);    ......}

ViewCompat類并非是在方法層面進行版本判斷然后調用不同的方法, 而是在類的層面上做的, 也就是說在調用方法時并沒有判斷版本的調用, 因為一臺手機的版本在開機到關機期間是不可能發生變化的, 所以只需要判斷一次, 而這次判斷放在了類的靜態初始化塊里.

static final ViewCompatImpl IMPL;  static {    final int version = android.os.Build.VERSION.SDK_INT;    if (version >= 21) {      IMPL = new LollipopViewCompatImpl();    } else if (version >= 19) {      IMPL = new KitKatViewCompatImpl();    } else if (version >= 17) {      IMPL = new JbMr1ViewCompatImpl();    } else if (version >= 16) {      IMPL = new JBViewCompatImpl();    } else if (version >= 14) {      IMPL = new ICSViewCompatImpl();    } else if (version >= 11) {      IMPL = new HCViewCompatImpl();    } else if (version >= 9) {      IMPL = new GBViewCompatImpl();    } else if (version >= 7) {      IMPL = new EclairMr1ViewCompatImpl();    } else {      IMPL = new BaseViewCompatImpl();    }  }

這樣我們就得到了針對各個版本的不同實現.

但是有些方法的實現在跨越幾個版本的時候是不變的, 有些方法又有可能每次都變, 如何實現高效的代碼復用呢? 那就是繼承+重寫.

比如BaseViewCompatImpl這個類是基類, 實現ViewCompatImpl接口, 把所有的方法都實現一次

static class BaseViewCompatImpl implements ViewCompatImpl {    ......    public boolean canScrollHorizontally(View v, int direction) {      return (v instanceof ScrollingView) &&        canScrollingViewScrollHorizontally((ScrollingView) v, direction);    }    public boolean canScrollVertically(View v, int direction) {      return (v instanceof ScrollingView) &&          canScrollingViewScrollVertically((ScrollingView) v, direction);    }    ......    @Override    public boolean isOpaque(View view) {      final Drawable bg = view.getBackground();      if (bg != null) {        return bg.getOpacity() == PixelFormat.OPAQUE;      }      return false;    }    ......    }

但是這些實現基本上都是空的, 或者無效的, 或者是一些workaround, 這也很正常, 因為確實不可能讓每個方法都做到兼容, 只能盡量讓他的版本支持多一點, 兼容性方法本來就有很多問題. 以上面這三個方法為例, 前兩個方法都是api 14出現的方法, 在14以下基本上等于是直接返回了false(這里低版本是僅對ScollingView提供了支持, ScollingView有三個基類, 其中一個是RecyclerView), google顯然沒有想到什么好的方法在低版本提供對這個方法的支持, 所以干脆就在api小于14時一直使用這個實現, 而isOpaque則是類似workaround的方法, 在api 7時, isOpaque被正式添加到View類中, 所以在api 7我們可以直接調View的isOpaque, 那么應該怎么寫代碼呢? 應當新建一個類, 繼承BaseViewCompatImpl, 重寫isOpaque方法, 也就是下面這樣:

static class EclairMr1ViewCompatImpl extends BaseViewCompatImpl {    @Override    public boolean isOpaque(View view) {      return ViewCompatEclairMr1.isOpaque(view);    }    ......  }

而其他沒有更好兼容方案的方法我們都不管, 那么api 9如果某些方法又有了更好的實現, 或者可以直接調用系統的api了, 就再新建一個類GBViewCompatImpl, 這個類需要繼承EclairMr1ViewCompatImpl.

同理, 我們在api 14對應的類ICSViewCompatImpl中自然就會看到canScrollHorizontally和canScrollVertically的新的實現, 而ICSViewCompatImpl必然繼承自HCViewCompatImpl.

就這樣慢慢的演化, 像串銅錢一樣, 每一個新的類對應一個新的版本(版本之間不需要連續), 同時繼承自前一個版本的類, 在實現類的繼承樹上越接近葉子, 這個實現類的能力就越強.

最后看一下我們在代碼里面使用這個類時的調用代碼, 比如我要調用canScrollVertically方法, 那么我的代碼一定是ViewCompat. canScrollVertically(v, dy), 看看這個方法對應的代碼

public static boolean canScrollHorizontally(View v, int direction) {    return IMPL.canScrollHorizontally(v, direction);} 

ViewCompat相當于是一個中介, 它自己其實什么都不懂, 但是它認識一個懂的人IMPL, 它將所有的調用都交給了IMPL, 而IMPL在ViewCompat這個類加載時就已經根據當前系統版本實例化了, 不需要再判斷版本了.

關于具體的使用請查看 官方文檔

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 华安县| 凉城县| 招远市| 固镇县| 桑植县| 靖安县| 阜平县| 京山县| 凌源市| 广昌县| 当涂县| 梨树县| 句容市| 巧家县| 罗城| 东辽县| 黑河市| 白朗县| 富蕴县| 湖口县| 阿图什市| 沙湾县| 五常市| 达孜县| 延庆县| 涟水县| 德惠市| 邵阳县| 洛川县| 隆安县| 高台县| 威远县| 健康| 定襄县| 定兴县| 平舆县| 武鸣县| 和政县| 侯马市| 嘉义市| 神木县|