Android 中高級面試題:Activity是如何實現LifecycleOwner的?

我們都知道Activity可作爲LifecycleOwner爲LiveData的使用提供條件,那麼Activity是如何實現LifecycleOwner的呢?

Activity雖然實現了LifecycleOwner接口,但是並沒有實現相關處理,而是通過添加一個Fragment來代理Lifecycle的分發。這種通過Fragment代理Activity行爲的設計在其他一些庫也經常出現,相對來說更加無侵和優雅。

1、SupportActivity

Activity通過繼承SupportActivity實現LifecycleOwner接口。注意在AndroidX中SupportActivity改名爲ComponentActivity。

public class SupportActivity extends Activity implements LifecycleOwner {

    ...

    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    ...

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
        super.onSaveInstanceState(outState);
    }

    ...

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

SupportActivity聲明瞭mLifecycleRegistry對象,但是沒有直接使用其進行生命週期的分發,而是被ReportFragment通過activity.getLifecycle()獲取使用。

2、ReportFragment

SupportActivity在onCreate爲自己添加了ReportFragment:

@RestrictTo(LIBRARY_GROUP)
public class SupportActivity extends Activity implements LifecycleOwner {
  // ...

  @Override
  @SuppressWarnings("RestrictedApi")
  protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      ReportFragment.injectIfNeededIn(this);
  }

  // ...
}

injectIfNeededIn是ReportFragment的靜態方法:

public static void injectIfNeededIn(Activity activity) {
    // ProcessLifecycleOwner should always correctly work and some activities may not extend
    // FragmentActivity from support lib, so we use framework fragments for activities
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        // Hopefully, we are the first to make a transaction.
        manager.executePendingTransactions();
    }
}

3、低版本Activity兼容Lifecycle

SupportActivity是伴隨Lifecycle纔出現的,android.arch.lifecycle:extensions爲早期還沒有繼承SupportActivity的Activity也提供了支持,通過LifecycleDispatcher實現ReportFragment的注入:

class LifecycleDispatcher {

    static void init(Context context) {
        if (sInitialized.getAndSet(true)) {
            return;
        }
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
        private final FragmentCallback mFragmentCallback;

        DispatcherActivityCallback() {
            mFragmentCallback = new FragmentCallback();
        }

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            if (activity instanceof FragmentActivity) {
                ((FragmentActivity) activity).getSupportFragmentManager()
                        .registerFragmentLifecycleCallbacks(mFragmentCallback, true);
            }
            ReportFragment.injectIfNeededIn(activity);
        }

    }
}

之前還疑惑爲什麼ReportFragment的實現不寫到SupportActivity中去,看到這裏終於理解了其存在的意義了吧。

LifecycleDispatcher並不需要在Application中調用,他通過ContentProvider實現初始化。

public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        ProcessLifecycleOwner.init(getContext());
        return true;
    }    
}

在android.arch.lifecycle:extensionsaar的AndroidManifest中註冊:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.arch.lifecycle.extensions" >

    <uses-sdk android:minSdkVersion="14" />

    <application>
        <provider
            android:name="android.arch.lifecycle.ProcessLifecycleOwnerInitializer"
            android:authorities="${applicationId}.lifecycle-trojan"
            android:exported="false"
            android:multiprocess="true" />
    </application>

</manifest>

${applicationId}佔位符,避免authroities衝突。

可見在無侵這件事情上做到了極致,這種無侵的初始化方法非常值得我們借鑑和使用。

4、兩種Fragment

通過上面分析,我們知道Activity是通過ReportFragment代理了LifecycleOwner的實現。那麼在Activity中添加的LifecycleOwner與Activity的Fragment的生命週期是否一致呢?答案是否定的。

Android中存在兩種Fragment有兩種:

1、SDK自帶的android.app.Fragment。

2、Support包中的android.support.v4.app.Fragment(AndroidX也歸爲此類)。

由於前者已經被@Deprecated,所以現在普遍使用的是後者,也就是Support或者AndroidX的Fragment。而出於低版本兼容性的考慮,ReportFragment是前者。

Activity對於兩種Fragment生命週期回調的實際並不相同,以onResume和onStart爲例,Activity回調的實際如下表:

onStart onResume
android.app.fragment Activity.performStart(2) Activity.onResume(3)
support fragment Activity.onStart(1) Activity.onPostResume(4)

上面表格中()中的數字表示依次執行的順序,所以你會發現,sdk fragment的onStart晚於support fragment,而onResume卻更早執行。

Activity的LifecycleOwner雖然是基於Fragment實現的,但是同一個Activity的LifecycleOwner與Fragment的生命週期回調實際並不一致。

這在我們的開發重要特別注意,不要讓視圖Fragment和LifecycleOwner的生命週期中的處理產生時序上的依賴關係。

5、總結

通過源碼分析Activity對於LifecycleOwner的實現後,我們得到以下結論:

1、Activity不直接調用HandleLifecycleEvent進行生命週期的分發,而是通過ReportFragment實現。

2、ReportFragment的注入和過程全程無侵,值得我們借鑑和學習。

3、同一個Activity,其LifecycleOwner與Fragment的生命週期回調實際並不一致,需要特別注意。

大廠面試前的複習準備

接下來分享的系統學習資源以詳解各大互聯網公司的 Android 常見面試題爲主線,從面試的角度帶你介紹必備知識點,以及該知識點在項目中的實際應用

幫你在現在的基礎上,重新梳理和建立 Android 開發的知識體系。無論是你短期內想提升 Android 內功實力,突破自己工作中的能力瓶頸,還是準備參加 Android 面試,都會在這份資料中有所一些收穫。

從架構基礎開始,分了8個模塊來逐步從基礎進階到架構師的環節:

多餘的話就不講了,接下來將分享面試的一個複習路線,如果你也在準備面試但是不知道怎麼高效複習,可以參考一下我的複習路線,有任何問題也歡迎一起互相交流,加油吧!

首先是超級詳細得不能再詳細的Android開發學習思維導圖,因爲圖片實在是太大了,所以我就只把二級目錄的內容放出來,更加詳細的你們可以點擊這裏

接下來就需要梳理知識,提升儲備了!(Android移動架構師七大專題學習資源)

  • 架構師築基必備技能:深入Java泛型+註解深入淺出+併發編程+數據傳輸與序列化+Java虛擬機原理+反射與類加載+動態代理+高效IO

  • Android高級UI與FrameWork源碼:高級UI晉升+Framework內核解析+Android組件內核+數據持久化

  • 360°全方面性能調優:設計思想與代碼質量優化+程序性能優化+開發效率優化

  • 解讀開源框架設計思想:熱修復設計+插件化框架解讀+組件化框架設計+圖片加載框架+網絡訪問框架設計+RXJava響應式編程框架設計+IOC架構設計+Android架構組件Jetpack

  • NDK模塊開發:NDK基礎知識體系+底層圖片處理+音視頻開發

  • 微信小程序:小程序介紹+UI開發+API操作+微信對接

  • Hybrid 開發與Flutter:Html5項目實戰+Flutter進階

知識梳理完之後,就需要進行查漏補缺,所以針對這些知識點,我手頭上也準備了不少的電子書和筆記,這些筆記將各個知識點進行了完美的總結。

然後再是通過源碼來系統性地學習

只要是程序員,不管是Java還是Android,如果不去閱讀源碼,只看API文檔,那就只是停留於皮毛,這對我們知識體系的建立和完備以及實戰技術的提升都是不利的。

真正最能鍛鍊能力的便是直接去閱讀源碼,不僅限於閱讀各大系統源碼,還包括各種優秀的開源庫。

刷大廠面試題備戰,增加大廠通過率

歷時半年,整理了這份市面上最全面的安卓面試題解析大全。

1.可以通過目錄索引直接翻看需要的知識點,查漏補缺。
2.五角星數表示面試問到的頻率,代表重要推薦指數

以上這些內容均免費分享給大家,需要完整版的朋友,點這裏可以看到全部內容。或者點擊 【這裏】 查看獲取方式。

最後還有耗時一年多整理的一系列Android學習資源:Android源碼解析、Android第三方庫源碼筆記、Android進階架構師七大專題學習、歷年BAT面試題解析包、Android大佬學習筆記等等,這些內容均免費分享給大家。

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