Android 談談封裝那些事 --BaseActivity 和 BaseFragment(二)

1.前言

昨天談了BaseActivity的封裝,
Android談談封裝那些事--BaseActivity和BaseFragment(一)
有不少小夥伴提了不少建議,好比:javascript

  • 通用標題欄能夠自定義View而不放在Base裏面,代碼更統一
  • BaseEventActivity裏面應該留出開關保證不須要Bus的Activity使用
  • BaseStatusActivity裏面就一個方法不必新建一個
  • 還有一些小的細節

在這裏感謝你們的建議了啊。我修改了一部分,後面會慢慢優化,最後在HLibrary裏面貼出最優代碼。還有那個BaseStatusActivity(沉浸欄)的也會繼續優化的。接下來談談BaseFragment的封裝,其實主要仍是關於Fragment的懶加載問題。java

2.Fragment相關知識點

  • 生命週期
  • Fragment的使用:靜態、動態
  • Fragment應注意到的問題
  • ......

在這裏就不詳細介紹了,想了解的能夠看個人這篇文章:網絡

你真的會用Fragment了麼?-Fragment解析ide

1.Fragment使用場景

咱們能夠看到市場的APP通常都是用底部Tab+fragment切換爲總體架子的,或者經過viewpager做爲容器嵌套fragment,再複雜點的就是fragment嵌套fragment,某書、某條等等都是這樣;post

2.遇到的問題

這樣的話咱們遇到的問題就是當fragment不少組合使用的時候,每一個fragment裏面都會加載數據或者執行動畫等比較複雜的業務邏輯時,致使咱們的APP進入時屏幕卡頓,性能不好,一點都不流暢。即使是咱們在使用viewpager做爲容器的時候設置預加載setOffscreenPageLimit()這個方法,其實你會發現根本不會起做用。
至於viewpager這個預加載方法爲何不行?咱們能夠看一下viewpager源碼:性能


咱們能夠看到DEFAULT_OFFSCREEN_PAGES 這裏就定義了默認值是1,若是你調用該方法傳進來的值小於1是無效的,會被強行的拽回1。並且DEFAULT_OFFSCREEN_PAGES 這個值是private的,子類繼承ViewPager也是不可見的。
網上有的說能夠將viewpager的源碼複製下來粘到本身的類裏面將這個默認值改成0,這個目前還沒試過,即便能夠感受也有些彆扭,更況且咱們使用場景也不必定須要viewpager呢

3.Fragment懶加載

這是靠Fragment裏有一個setUserVisibleHint(boolean isVisibleToUser)的方法,咱們能夠在這個方法裏作判斷,當其True可見時(即切換到某一個具體Fragment)時纔去加載數據,這樣能夠省流量。
具體怎麼去操做呢?優化

  • 預加載初始化數據和組件等輕量操做
  • 切換tab到第一次可見時執行網絡請求
  • 四種狀態:第一次可見狀態、可見狀態、第一次不可見狀態、不可見狀態
  • 銷燬時處理解註冊、銷燬廣播等問題

3.BaseFragment封裝

1.初始化xml文件

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (getContentViewLayoutID() != 0) {
            return inflater.inflate(getContentViewLayoutID(), null);
        } else {
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }

        protected abstract int getContentViewLayoutID();複製代碼

2.註解綁定以及初始化組件

@Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ButterKnife.bind(this,view);
        initViewsAndEvents(view);
    }

    protected abstract void initViewsAndEvents(View view);複製代碼

3.四種「見」的狀態拆分

@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initPrepare();
    }

    private synchronized void initPrepare() {
        if (isPrepared) {
            onFirstUserVisible();
        } else {
            isPrepared = true;
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            if (isFirstVisible) {
                isFirstVisible = false;
                initPrepare();
            } else {
                onUserVisible();
            }
        } else {
            if (isFirstInvisible) {
                isFirstInvisible = false;
                onFirstUserInvisible();
            } else {
                onUserInvisible();
            }
        }
    }

    protected abstract void onFirstUserVisible();
    protected abstract void onUserVisible();
    private void onFirstUserInvisible() { }
    protected abstract void onUserInvisible();複製代碼

4.最後解註冊銷燬等工做

@Override
    public void onDestroy() {
        DetoryViewAndThing();
        super.onDestroy();
    }

    protected abstract void DetoryViewAndThing();複製代碼

5.跳轉界面等方法

/** * 打開一個Activity 默認 不關閉當前activity */
    public void gotoActivity(Class<?> clz) {
        gotoActivity(clz, false, null);
    }

    public void gotoActivity(Class<?> clz, boolean isCloseCurrentActivity) {
        gotoActivity(clz, isCloseCurrentActivity, null);
    }

    public void gotoActivity(Class<?> clz, boolean isCloseCurrentActivity, Bundle ex) {
        Intent intent = new Intent(mActivity, clz);
        if (ex != null) intent.putExtras(ex);
        startActivity(intent);
        if (isCloseCurrentActivity) {
            mActivity.finish();
        }
    }複製代碼

最後提一個小問題吧:就是說若是你沒有用Fragment懶加載的話而是用的viewpager的預加載,若是你沒有本身定義默認預加載個數的話,那麼默認確定是會提早加載的,加入你當前fragment相鄰的fragment裏面有動畫或者視頻播放的話,切換到當前fragment時候下個fragment裏面的動畫或者視頻就已經開始執行了,注意一下。
到此個人base就告一段落了,不少不合理的地方,我接下來私下也會去聽取小夥伴們的意見進行修改,而後最後在HLibrary裏面貼出來的,很是感謝你們。動畫

相關文章
相關標籤/搜索