ViewPager切換Fragment生命週期變化

很久沒有寫博客了,今天學習了MD的TabLayout ,使用到了ViewPager,於是對於很久以來的一個疑問:ViewPager切換Fragment生命週期是如何變化的進行了一個測試。

本文研究了:
1. ViewPager2個相鄰Fragment之間的切換生命週期變化
2. ViewPager間隔3個Fragment之間的切換生命週期變化
3. ViewPager間隔4個Fragment之間的切換生命週期變化

如果看過類似文章請自行跳過。

上代碼

佈局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolBar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    </android.support.v4.view.ViewPager>

    <android.support.design.widget.TabLayout
        android:id="@+id/tl_tab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white">

    </android.support.design.widget.TabLayout>

</LinearLayout>

MainActivity

package tyh.com.tablayout;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import butterknife.ButterKnife;
import butterknife.InjectView;

public class MainActivity extends AppCompatActivity {

    @InjectView(R.id.vp_content)
    ViewPager vpContent;
    @InjectView(R.id.tl_tab)
    TabLayout tlTab;
    @InjectView(R.id.toolBar)
    Toolbar toolBar;

    private List<String> tabIndicators;
    private List<Integer> tabImages;
    private List<Fragment> tabFragments;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);

        initToolBar();
        initContent();
        initTab();
    }

    private void initToolBar() {
        toolBar.setTitle("TabLayout");
        toolBar.setTitleTextColor(getResources().getColor(R.color.colorToolBarTitle));
    }

    private void initTab() {
        tlTab.setTabMode(TabLayout.MODE_FIXED);
        tlTab.setSelectedTabIndicatorHeight(0);
        ViewCompat.setElevation(tlTab, 10);
        tlTab.setupWithViewPager(vpContent);
        for (int i = 0; i < tabIndicators.size(); i++) {
            TabLayout.Tab itemTab = tlTab.getTabAt(i);
            if (itemTab != null) {
                itemTab.setCustomView(R.layout.item_tab_layout_custom);
                TextView itemTv = (TextView) itemTab.getCustomView().findViewById(R.id.itemTextView);
                ImageView itemIv = (ImageView) itemTab.getCustomView().findViewById(R.id.itemImageView);
                itemTv.setText(tabIndicators.get(i));
                itemIv.setImageResource(tabImages.get(i));
            }
        }
        tlTab.getTabAt(0).getCustomView().setSelected(true);

    }

    private void initContent() {
        tabIndicators = new ArrayList<>();
        tabIndicators.add("消息");
        tabIndicators.add("任務");
        tabIndicators.add("團隊");
        tabIndicators.add("部門");
        tabImages = new ArrayList<>();
        tabImages.add(R.drawable.main_tabs_message_normal);
        tabImages.add(R.drawable.main_tabs_task_normal);
        tabImages.add(R.drawable.main_tabs_team_normal);
        tabImages.add(R.drawable.main_tabs_depart_normal);
        tabFragments = new ArrayList<>();
        for (String s : tabIndicators) {
            tabFragments.add(TabContentFragment.newInstance(s));
        }
        ContentPagerAdapter contentAdapter = new ContentPagerAdapter(getSupportFragmentManager());
        vpContent.setAdapter(contentAdapter);
    }

    private class ContentPagerAdapter extends FragmentPagerAdapter {

        public ContentPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return tabFragments.get(position);
        }

        @Override
        public int getCount() {
            return tabIndicators.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return tabIndicators.get(position);
        }
    }
}

TabContentFragment

public class TabContentFragment extends Fragment {

    private String text;

    public TabContentFragment(String text) {
        this.text = text;
    }

    public static Fragment newInstance(String s) {
        return new TabContentFragment(s);
    }

    @Override
    public void onAttach(Context context) {
        Log.e("TYH", text + "onAttach");
        super.onAttach(context);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.e("TYH", text + "onCreate");
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.e("TYH", text + "onCreateView");
        TextView textView = new TextView(getContext());
        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        textView.setLayoutParams(layoutParams);
        textView.setGravity(Gravity.CENTER);
        textView.setText(text);
        return textView;
    }

    @Override
    public void onStart() {
        Log.e("TYH", text + "onStart");
        super.onStart();
    }

    @Override
    public void onResume() {
        Log.e("TYH", text + "onResume");
        super.onResume();
    }

    @Override
    public void onPause() {
        Log.e("TYH", text + "onPause");
        super.onPause();
    }

    @Override
    public void onStop() {
        Log.e("TYH", text + "onStop");
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        Log.e("TYH", text + "onDestroyView");
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        Log.e("TYH", text + "onDestroy");
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        Log.e("TYH", text + "onDetach");
        super.onDetach();
    }
}

效果圖

這裏寫圖片描述

進入正片

1. ViewPager2個相鄰Fragment之間的切換生命週期變化

消息 ->任務

05-09 14:47:39.593 31509-31509/tyh.com.tablayout E/TYH: 團隊onAttach
05-09 14:47:39.593 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreate
05-09 14:47:39.593 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreateView
05-09 14:47:39.603 31509-31509/tyh.com.tablayout E/TYH: 團隊onStart
05-09 14:47:39.603 31509-31509/tyh.com.tablayout E/TYH: 團隊onResume

大家可能有疑問,奇怪!怎麼沒走任務Fragment的任何生命週期?
答:這是因爲進入MainActivity時Fragment 聲明週期發生瞭如下變化:

05-09 14:48:14.170 31509-31509/tyh.com.tablayout E/TYH: 消息onAttach
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 消息onCreate
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 消息onCreateView
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 消息onStart
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 消息onResume
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 任務onAttach
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 任務onCreate
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 任務onCreateView
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 任務onStart
05-09 14:48:14.180 31509-31509/tyh.com.tablayout E/TYH: 任務onResume

也就是說,進入界面之後。
ViewPager默認會給我們初始化好前面2個Fragment的內容。
當我們切換到第二個Fragment的時候,初始化好第三個Fragment。

任務 ->團隊

05-09 14:55:26.932 31509-31509/tyh.com.tablayout E/TYH: 消息onPause
05-09 14:55:26.932 31509-31509/tyh.com.tablayout E/TYH: 消息onStop
05-09 14:55:26.932 31509-31509/tyh.com.tablayout E/TYH: 消息onDestroyView
05-09 14:55:26.932 31509-31509/tyh.com.tablayout E/TYH: 部門onAttach
05-09 14:55:26.932 31509-31509/tyh.com.tablayout E/TYH: 部門onCreate
05-09 14:55:26.942 31509-31509/tyh.com.tablayout E/TYH: 部門onCreateView
05-09 14:55:26.942 31509-31509/tyh.com.tablayout E/TYH: 部門onStart
05-09 14:55:26.942 31509-31509/tyh.com.tablayout E/TYH: 部門onResume

由生命週期可見,任務到團隊的切換過程中,將消息Fragment給幹掉了,把部門給初始化完畢了。

團隊 ->部門

05-09 14:57:18.371 31509-31509/tyh.com.tablayout E/TYH: 任務onPause
05-09 14:57:18.371 31509-31509/tyh.com.tablayout E/TYH: 任務onStop
05-09 14:57:18.371 31509-31509/tyh.com.tablayout E/TYH: 任務onDestroyView

部門 ->團隊

05-09 15:00:50.918 31509-31509/tyh.com.tablayout E/TYH: 任務onCreateView
05-09 15:00:50.918 31509-31509/tyh.com.tablayout E/TYH: 任務onStart
05-09 15:00:50.918 31509-31509/tyh.com.tablayout E/TYH: 任務onResume

團隊->任務

05-09 15:01:15.134 31509-31509/tyh.com.tablayout E/TYH: 消息onCreateView
05-09 15:01:15.144 31509-31509/tyh.com.tablayout E/TYH: 部門onPause
05-09 15:01:15.144 31509-31509/tyh.com.tablayout E/TYH: 部門onStop
05-09 15:01:15.144 31509-31509/tyh.com.tablayout E/TYH: 部門onDestroyView
05-09 15:01:15.144 31509-31509/tyh.com.tablayout E/TYH: 消息onStart
05-09 15:01:15.144 31509-31509/tyh.com.tablayout E/TYH: 消息onResume

任務->消息

05-09 15:02:07.890 31509-31509/tyh.com.tablayout E/TYH: 團隊onPause
05-09 15:02:07.890 31509-31509/tyh.com.tablayout E/TYH: 團隊onStop
05-09 15:02:07.890 31509-31509/tyh.com.tablayout E/TYH: 團隊onDestroyView

滑動時幾個Fragment生命週期與切換相同

2. ViewPager間隔3個Fragment之間的切換生命週期變化

接下來貼出間隔3個Fragment之間切換生命週期變化

消息->團隊

05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 團隊onAttach
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreate
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreateView
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 團隊onStart
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 團隊onResume
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 部門onAttach
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 部門onCreate
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 部門onCreateView
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 部門onStart
05-09 15:04:41.284 31509-31509/tyh.com.tablayout E/TYH: 部門onResume
05-09 15:04:41.614 31509-31509/tyh.com.tablayout E/TYH: 消息onPause
05-09 15:04:41.614 31509-31509/tyh.com.tablayout E/TYH: 消息onStop
05-09 15:04:41.614 31509-31509/tyh.com.tablayout E/TYH: 消息onDestroyView

可見首先是團隊的初始化,接下來是部門的初始化,再者是消息的銷燬

3. ViewPager間隔4個Fragment之間的切換生命週期變化

接下來貼出間隔4個Fragment之間切換生命週期變化

消息->部門

05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 部門onAttach
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 部門onCreate
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 部門onCreateView
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 部門onStart
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 部門onResume
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 團隊onAttach
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreate
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 團隊onCreateView
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 團隊onStart
05-09 15:07:02.684 31509-31509/tyh.com.tablayout E/TYH: 團隊onResume
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 任務onPause
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 任務onStop
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 任務onDestroyView
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 消息onPause
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 消息onStop
05-09 15:07:03.135 31509-31509/tyh.com.tablayout E/TYH: 消息onDestroyView

首先是部門的初始化,接下來是團隊的初始化,再者是任務和消息的銷燬

總結

ViewPager從其內部Fragment的生命週期的變化大家可以看出來一個規律:
1. 當左右可以滑動時,始終保持左右的Fragment初始化完畢,可以說是一個預加載效果
2. 當不處於當前展示的位置左右時,執行onPause、onStop、onDestroyView方法

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