Android 源碼分析實戰 - 把代碼寫得更優雅

1. 源碼版本適配

一般情況下來說,如果涉及到源碼反射,通常都需要適配各個版本,因此我們把與 so 修複相關的各大版本源碼都翻出來,具體的源碼細節,大家可以參考《Android 源碼分析實戰 - 動態加載修復 so 庫》

    public void injectLoadPath(String soDir) throws Exception {
        ...
        int version = Build.VERSION.SDK_INT;
        if(version < Build.VERSION_CODES.M){
            nativeLibraryPathElementsField = ReflectUtil.getFiled(pathList,"nativeLibraryDirectories");
        }else if(version >= Build.VERSION_CODES.M){
            nativeLibraryPathElementsField = ReflectUtil.getFiled(pathList, "nativeLibraryPathElements");
        }
        ...
        Object firstElement = null;
        if(version < Build.VERSION_CODES.M){
            firstElement = new File(soDir);
        }else if(version >= Build.VERSION_CODES.M  && version < Build.VERSION_CODES.O){
            Constructor<?> elementConstructor = elementClass.getConstructor(File.class);
            elementConstructor.setAccessible(true);
            firstElement = elementConstructor.newInstance(new File(soDir));
        }else if(version >= Build.VERSION_CODES.O){
            Constructor<?> elementConstructor = elementClass.getConstructor(File.class, boolean.class, File.class, DexFile.class);
            elementConstructor.setAccessible(true);
            firstElement = elementConstructor.newInstance(new File(soDir),true, null, null);
        }
        ...
    }

寫出上面這樣的代碼,個人覺得應該差不多了。但我們平時寫代碼的時候,往往是想過要把代碼寫得更優雅,但就是感覺不知道該怎麼寫?因此我建議大家關於設計模式,一定要仔細學習理解但不要生搬硬套,學過之後要選擇性的忘記這些內容。我也曾聽同學說過,千萬不要學設計模式,設計模式會固化我們的思想,希望大家不要有這樣的錯覺。

2. AppCompatDelegate 源碼分析

我們可以先參考 Android 源碼,也就是看下 Google 工程師,是怎麼寫源碼適配代碼的

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        getDelegate().installViewFactory();
        getDelegate().onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    public AppCompatDelegate getDelegate() {
        if (mDelegate == null) {
            mDelegate = AppCompatDelegate.create(this, this);
        }
        return mDelegate;
    }

    private static AppCompatDelegate create(Context context, Window window,
            AppCompatCallback callback) {
        final int sdk = Build.VERSION.SDK_INT;
        if (sdk >= 23) {
            return new AppCompatDelegateImplV23(context, window, callback);
        } else if (sdk >= 14) {
            return new AppCompatDelegateImplV14(context, window, callback);
        } else if (sdk >= 11) {
            return new AppCompatDelegateImplV11(context, window, callback);
        } else {
            return new AppCompatDelegateImplV7(context, window, callback);
        }
    }

3. 改造版本適配代碼

身經百戰後我們自然知道該怎麼寫,並不一定非得模仿系統源碼,就按照原來的代碼也行,這裏我只是舉一個例子。

public class SoHotFix {
    private SoFix mSoFix;
    public SoHotFix(Context context) {
        Context applicationContext = context.getApplicationContext();
        // 各大版本適配
        final int sdk = Build.VERSION.SDK_INT;
        if (sdk >= Build.VERSION_CODES.O) {
            mSoFix = new SoFixImpV26(applicationContext);
        } else if (sdk >= Build.VERSION_CODES.M) {
            mSoFix = new SoFixImpV23(applicationContext);
        } else {
            mSoFix = new SoFixImpV20(applicationContext);
        }
    }

    public void injectLoadPath(String soDir) throws Exception {
        mSoFix.hotFix(soDir);
    }
}

這是我們隨便挑的一個簡單的例子,只是想表達源碼其實是最好的學習資料,Linus Torvalds 曾說過 Read The Fucking Source Code。

視頻地址:https://pan.baidu.com/s/1COarOAlmOPCUlKsazho0Cw 
視頻密碼:8lr0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章