天天看點

Jetpack 元件庫 | 用代碼解析 Lifecycles 庫,讓代碼更容易維護

作者:願天堂沒有代碼

引言

Jetpack 是一個由多個庫組成的套件,可幫助開發者遵循最佳做法,減少樣闆代碼并編寫可在各種 Android 版本和裝置中一緻運作的代碼,讓開發者精力集中編寫重要的代碼
Jetpack 元件庫 | 用代碼解析 Lifecycles 庫,讓代碼更容易維護

Jetpack 是 Google 為解決 Android 開發碎片化,打造成熟健康生态圈提出的戰略規劃,是 Google 對 Android 未來提出的發展方向,同時它也是衆多優秀 Android 元件的集合

Lifecycles 庫是拿來幹什麼的

這個庫從系統架構層去管理具有生命周期的元件,例如activity, fragment。讓開發更友善地去管理自己應用裡需要和activity或者fragment綁定的元件,讓代碼更容易維護。

也許有點抽象,舉個例子說明一下,比如有個需求,需要在一個界面比較頻繁更新地理位置資訊。當Activity走了onstop之後,你應該也要暫停更新地理位置,或者當Activity走destroy後,你要釋放一些資源

下面用一些代碼執行個體解析一下,你的代碼也許是這樣的:

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // 開始連接配接位置服務
    }

    void stop() {
        // 停止連接配接位置服務
    }
    
    void destroy(){
        //釋放資源
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, new Callback(){
            //回調更新UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        //綁定actiivty的onStart周期函數
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        //綁定actiivty的onStop周期函數
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        myLocationListener.destroy();
        //綁定actiivty的onDestroy周期函數
    }
}           

上面的代碼在簡單app看起來也許還好,但是當你activity業務邏輯比較多,可能包含很多和生命周期綁定的自定義元件,代碼長期積累就很難維護啦。

下面在看看使用Lifecycles庫的代碼做對比:

class MyLocationListener implements LifecycleObserver{
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
        // 開始連接配接位置服務
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // 停止連接配接位置服務
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void destroy(){
        //釋放資源
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, new Callback(){
            //回調更新UI
        });
        getLifecycle().addObserver(myLocationListener);
    }
}    
複制代碼           

MyLocationListener實作LifecycleObserver, 在相應的方法添加OnLifecycleEvent注解就可以收到相應的回調,在Activity的onCreate方法裡調用 getLifecycle().addObserver(myLocationListener)即可。下面結合源碼分析Lifecycles庫, 去更好地學習這個庫。

Lifecycles 庫核心類與結構

Support Library 26.1.0 版本以及之後的版本,AppCompatActivity和Fragment實作了LifecycleOwner。

Lifecycles庫核心就是訂閱者模式。

  • LifecycleOberver類:隻是個空接口, 安卓生命周期觀察者
  • Lifecycle類: 是個抽象類,定義了安卓生命周期對象,有3個方法,添加觀察者,移除觀察者,擷取目前狀态
  • LifecycleOwner類: 是個接口, 安卓生命周期的擁有者
  • LifecycleRegistry: Lifecycle的實作類,實作了添加、移除觀察者,分派觀察者狀态等

自定義類實作LifecycleOberver接口,在方法中添加OnLifecycleEvent注解就可以收到相應生命周期的狀态

public @interface OnLifecycleEvent {
    Lifecycle.Event value();
}

public enum Event { 
    ON_CREATE,
    ON_START,
    ON_RESUME,
    ON_PAUSE,
    ON_STOP,
    ON_DESTROY,
    ON_ANY
}
//Event是Lifecycle内部類一個枚舉類, 分别定義了onCreate, onStart, onResume, onPause,onStop,onDestroy, onAny這幾個Event

public enum State {
    DESTROYED,
    INITIALIZED,
    CREATED,
    STARTED,
    RESUMED;

    public boolean isAtLeast(@NonNull State state) {
        return compareTo(state) >= 0;
    }
}//State也是Lifecycle内部類一個枚舉類, 定義了INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED幾種狀态           

Lifecycle的各個狀态一共有5個,記錄在枚舉State中, 依次是DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED;

代表分發的Event:

  • 當分發ON_CREATE事件時,State由INITIALIZED -> CREATED;
  • 當分發ON_START事件時, State由CREATED -> STARTED
  • 當分發ON_RESUME事件時, State由STARTED -> RESUMED
  • 當分發ON_PAUSE事件時, State由RESUMED -> STARTED
  • 當分發ON_STOP事件時, State由STARTED -> CREATED
  • 當分發ON_DESTROY事件時, State由CREATED -> DESTROYED

你會發現State沒STOPED和PAUSED的狀态, 當State=CREATED時, Activity大概是在onCreate調用後或者onStop調用後;當State=STARTED時, Activity大概是在onStart調用後或者onPause調用後

ComponentActivity 分發 Event 的過程

  • 下面截取部分ComponentActivity的關鍵代碼:
public class ComponentActivity extends Activity implements LifecycleOwner{
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this); //利用Fragment來分發
    }
    
        @CallSuper
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        mLifecycleRegistry.markState(Lifecycle.State.CREATED); //onSaveInstanceState是用來恢複Activity狀态的, 這裡記錄的狀态是CREATED
        super.onSaveInstanceState(outState);
    }
    
        @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry; //傳回LifecycleRegistry
    }
}           
  • 下面再看ReportFragment類關鍵代碼:
public static void injectIfNeededIn(Activity activity) { 
        // 為目前activity add 一個ReportFragment,用于分發event
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatch(Lifecycle.Event.ON_CREATE); //分發ON_CREATE Event
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);//分發ON_START Event
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatch(Lifecycle.Event.ON_RESUME);//分發ON_RESUME Event
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);//分發ON_PAUSE Event
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);//分發ON_STOP Event
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);//分發ON_DESTROY Event
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        // Activity是實作LifecycleOwner接口,這裡可以跳過
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
                //最終調用LifecycleRegistry.handleLifecycleEvent(event)處理event分發
            }
        }
    }           

ComponentActivity的是Event分發是通過添加一個ReportFragment, 通過重寫ReportFragment的onActivityCreated, onStart, onResume, onStop, onPause, onDestroy方法,最終交給LifecycleRegistry.handleLifecycleEvent(event)處理。

Fragment 分發 Event 的過程

  • 下面也是截去相關v4裡Fragment的相關源碼
LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

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

   void performCreate(Bundle savedInstanceState) {
        ...
        onCreate(savedInstanceState);
        ...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

    void performStart() {
        ...
        onStart();
        ...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    void performResume() {
        ...
        onResume();
        ...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }

    void performPause() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        ...
        onPause();
        ...
    }

    void performStop() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        ...
        onStop();
        ...
    }

    void performDestroy() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        ...
        onDestroy();
        ...
    }
複制代碼           

LifecycleRegistry.handleLifecycleEvent(event)處理。 至于LifecycleRegistry這個類更多的細節就不展開啦

自定義 LifecycleOwner

前面提到Support Library 26.1.0 版本以及之後的版本,AppCompatActivity和Fragment實作了LifecycleOwner, 如果你還用舊的版本或者繼承Activity, 你可以通過自定義Activity或者Fragment實作

  • 自定義實作代碼如下:
//可以單獨引入androidx.lifecycle:lifecycle-runtime:$lifecycle_version庫
public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        mLifecycleRegistry.markState(Lifecycle.State.STARTED);
    }
    
    ....

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

使用 ProcessLifecycleOwner 監聽整個 App 程序的前背景

要注意ON_CREATE的Event之後分發一次,ON_DESTROY不會分發

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(new LifecycleObserver() {

            private static final String TAG = "ProcessLifecycleOwner";

            @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
            public void onCreate(){
                Log.d(TAG, "onCreate: "); //應用啟動隻被調用一次
            }
            
            @OnLifecycleEvent(Lifecycle.Event.ON_START)
            public void onStart(){
                Log.d(TAG, "onStart: "); //應用啟動會調用一次, 從背景回來也會調用
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
            public void onResume(){
                Log.d(TAG, "onResume: "); //應用啟動會調用一次, 從背景回來也會調用
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
            public void onPause(){
                Log.d(TAG, "onPause: "); //按home鍵或者切換應用會調用
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
            public void onStop(){
                Log.d(TAG, "onStop: "); //按home鍵或者切換應用會調用
            }

        });
}               

要注意ON_PAUSE, ON_STOP的回調會有700毫秒的延遲, 官方的解析是保證不要由于配置更改而銷毀和重新Activity時不會分發任何事件。還有一點,如果你的app是多程序應用,ProcessLifecycleOwner隻能用來監聽主程序。

  • 下面簡單說一下ProcessLifecycleOwner的工作原理:
// ProcessLifecycleOwner 關鍵代碼
public class ProcessLifecycleOwner implements LifecycleOwner{
    
    private int mStartedCounter = 0; // 計數器
    private int mResumedCounter = 0; // 計數器
    
    void activityResumed() {
        mResumedCounter++;
        if (mResumedCounter == 1) {
            if (mPauseSent) {
                mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
                mPauseSent = false;
            } else {
                mHandler.removeCallbacks(mDelayedPauseRunnable);
            }
        }
    }

    void activityPaused() {
        mResumedCounter--;
        if (mResumedCounter == 0) {
            mHandler.postDelayed(mDelayedPauseRunnable, TIMEOUT_MS);
        }
    }
    
    void attach(Context context) {
        mHandler = new Handler();
        //mRegistry是LifecycleRegistry對象,依靠LifecycleRegistry分發Event,不多說
        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
        Application app = (Application) context.getApplicationContext();
        //利用registerActivityLifecycleCallbacks注冊callback監聽activity生命周期
        //細看activityResumed和activityPaused方法,通過Activity計數法來實作應用前背景的監聽
        app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                ReportFragment.get(activity).setProcessListener(mInitializationListener);
            }

            @Override
            public void onActivityPaused(Activity activity) {
                activityPaused();
            }

            @Override
            public void onActivityStopped(Activity activity) {
                activityStopped();
            }
        });
    }
    
    static void init(Context context) { // 初始化
        sInstance.attach(context);
    }
}

public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        //這是個ContentProvider,在onCreate方法初始化ProcessLifecycleOwner
        //主程序的第一個ContentProvider.onCreate是比Application.onCreate先調用的
        //這個ContentProvider會注冊在Androidmenifest中,進而不用再Application中進行ProcessLifecycleOwner初始化
        ProcessLifecycleOwner.init(getContext()); 
        return true;
    }
}               

LifecycleService 的使用

LifecycleService 繼承Service, 并實作LifecycleOwner, 可以自定義一個服務繼承LifecycleService來使用

  • 下面是代碼執行個體:
public class MyService extends LifecycleService {

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        getLifecycle().addObserver(new LifecycleObserver() {

            @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
            public void onCreate(){
                Log.d(TAG, "onCreate: ");
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_START)
            public void onStart(){
                Log.d(TAG, "onStart: ");
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
            public void onStop(){
                Log.d(TAG, "onStop: ");
            }
            
            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            public void onDestroy(){
                Log.d(TAG, "onDestroy: ");
            }

        });
    }
}           

總結以及其他的 Tips

Lifecycles 庫為 Jetpack 其他元件打下了基礎,通過LifecycleObserver觀察者減少對Activity, Fragment, 和Service這些具有生命周期類的依賴。

  • 是使用LifecycleService和ProcessLifecycleOwner需要引入android.arch.lifecycle:extensions:1.1.1庫,它并沒有包含在com.android.support:appcompat-v7:version中
  • 在使用到Lifecycles庫時最好在gradle引入apt編譯器庫annotationProcessor "android.arch.lifecycle:compiler:1.1.1", 沒引入這庫,對應注解@OnLifecycleEvent的方法就是使用反射來實作的,當引入這庫後,會在編譯時期自動生成YourObserverName_LifecycleAdapter類實作0反射提高性能。

最後這裡放上一張大佬推薦的 Android Jetpack 的思維腦圖,并根據腦圖整理了一份系統學習 Jetpack 的資料筆記;Jetpack 技術相關的知識點在筆記中都有詳細的解讀,并且把每個技術點整理成了 PDF 文檔(知識脈絡 + 諸多細節)有需要的小夥伴:可以私信發送 “腦圖” 或 "筆記"就可以免費領取了

Jetpack 元件庫 | 用代碼解析 Lifecycles 庫,讓代碼更容易維護
Jetpack 元件庫 | 用代碼解析 Lifecycles 庫,讓代碼更容易維護

好了,以上就是今天要分享的内容,大家覺得有用的話,可以點贊分享一下;如果文章中有什麼問題歡迎大家指正;歡迎在評論區或背景讨論哈~

繼續閱讀