前言
最近换了新工作,一直写业务,写的过程中碰到了viewPager结合Fragment的使用的场景,但是发现自己对此时Fragment的生命周期理解并不到位,在此做一下记录。
代码和布局文件
ActivityForViewPager.java
package com.xol.viewpagerfragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
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.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
/**
* Created by wwzhang on 2019/1/24
*/
public class ActivityForViewPager extends AppCompatActivity {
private ViewPager viewPager;
private TabLayout tabLayout;
private String tabs[] = {"A", "B", "C", "D", "E"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_for_viewpager);
initView();
}
private void initView() {
viewPager = (ViewPager) findViewById(R.id.vp_content);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), tabs));
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
/**
* fagment
*/
public static class ViewPagerFragment extends Fragment {
private static final String TAG = "ViewPagerFragment";
private String tab;
public static Fragment createFragment(Bundle bundle) {
Fragment fragment = new ViewPagerFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onAttach(Context context) {
tab = getArguments().getString("tab");
super.onAttach(context);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated: " + tab);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: " + tab);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: " + tab);
TextView textView = new TextView(container.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
textView.setPadding(25, 25, 25, 25);
textView.setGravity(Gravity.CENTER);
textView.setLayoutParams(params);
textView.setText(tab);
return textView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewCreated: " + tab);
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onStart() {
Log.d(TAG, "onStart: " + tab);
super.onStart();
}
@Override
public void onResume() {
Log.d(TAG, "onResume: " + tab);
super.onResume();
}
@Override
public void onPause() {
Log.d(TAG, "onPause: " + tab);
super.onPause();
}
@Override
public void onStop() {
Log.d(TAG, "onStop: " + tab);
super.onStop();
}
@Override
public void onDestroyView() {
Log.d(TAG, "onDestroyView: " + tab);
super.onDestroyView();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: " + tab);
super.onDestroy();
}
@Override
public void onDetach() {
Log.d(TAG, "onDetach: " + tab);
super.onDetach();
}
}
/**
* 适配器
*/
public static class ViewPagerAdapter extends FragmentPagerAdapter {
private String[] tabs;
public ViewPagerAdapter(FragmentManager fm, String[] tabs) {
super(fm);
this.tabs = tabs;
}
@Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putString("tab", tabs[position]);
// return null;
return ViewPagerFragment.createFragment(bundle);
}
@Override
public int getCount() {
return tabs.length;
}
@Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
}
}
activity_for_viewpager.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:padding="16dp"
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="ViewPager" />
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="@+id/vp_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
运行结果
Fragment典型周期图
viewPager 从A滑倒B输出日志
01-24 14:10:37.001 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreate: A
01-24 14:10:37.002 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreate: B
onCreateView: A
01-24 14:10:37.004 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onViewCreated: A
onActivityCreated: A
01-24 14:10:37.005 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onStart: A
onResume: A
onCreateView: B
01-24 14:10:37.006 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onViewCreated: B
onActivityCreated: B
01-24 14:10:37.008 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onStart: B
onResume: B
//上面为第一次打开该Activity日志输出
01-24 14:10:40.036 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreate: C
01-24 14:10:40.038 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreateView: C
01-24 14:10:40.039 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onViewCreated: C
onActivityCreated: C
onStart: C
onResume: C
// 上面为viewPager滑动到B Fragment的日志输出
01-24 14:10:40.812 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreate: D
01-24 14:10:40.813 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onPause: A
onStop: A
01-24 14:10:40.814 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onDestroyView: A
01-24 14:10:40.815 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreateView: D
01-24 14:10:40.817 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onViewCreated: D
onActivityCreated: D
01-24 14:10:40.818 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onStart: D
onResume: D
// 上面为viewPager滑动到C Fragment的日志输出
01-24 14:10:41.618 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreate: E
onPause: B
01-24 14:10:41.619 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onStop: B
onDestroyView: B
01-24 14:10:41.620 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onCreateView: E
01-24 14:10:41.622 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onViewCreated: E
01-24 14:10:41.623 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onActivityCreated: E
onStart: E
01-24 14:10:41.624 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onResume: E
// 上面为viewPager滑动到D Fragment的日志输出
01-24 14:10:42.720 1805-1805/com.xol.viewpagerfragment D/ViewPagerFragment: onPause: C
onStop: C
onDestroyView: C
// 上面为viewPager滑动到E Fragment的日志输出
日志分析
- 打开activity,viewPager没有滑动的时候,由于PagerFragmentAdapter 默认缓存三个Fragment(当前页和左右页面) 第一次当前页面为A Fragment 缓存右边页面为B Fragment;故开始日志输出为A-onCreate-onCreateView-onViewCreated-onActivityCreated-onStart-onResume B-onCreate-onCreateView-onViewCreated-onActivityCreated-onStart-onResume
- 当viewPager滑动到B Fragment时候,由于默认缓存三个Fragment,会预先生成C Fragment,故日志输出为C-onCreate-onCreateView-onViewCreated-onActivityCreated-onStart-onResume
- 当viewPager滑动到C Fragment,会预先生成D Fragment,移除A-Fragment(内存中依然存在);故日志输出为D-onCreate-onCreateView-onViewCreated-onActivityCreated-onStart-onResume A-onPause-onStop-onDestroyView
- 当viewPager由C Fragment 动到B Fragment时,A Fragment 会走 onCreateView-onViewCreated-onActivityCreated-onStart-onResume
总结
ViewPager 结合PagerFragmentAdapter滑动的过程中,默认会生成三个Fragment(当在viewPager开始和结尾的时候默认只会生成两个Fragment)包括当前Fragment和左右位置的Fragment,并且在滑动的过程中,会预先生成下一个Fragment,并销毁多余的Fragment,列当滑到C Fragment 的时候,A Fragment 会从view层面销毁,但并不会走Fragment的onDestroy和onDetach周期方法,当我们反向滑动,并重新预加载A Fragment时,此时 A Fragment 并不会走onAttach 和 onCreate方法,只会走onCreateView-onViewCreated-onActivityCreated-onStart-onResume
此时若想复用之前的View 可在内存中保存一个Fragment的根view,做非空判断,去复用已经创建过的view Fragment代码如下:
public static class ViewPagerFragment extends Fragment {
private static final String TAG = "ViewPagerFragment";
private String tab;
private View mRootView;
public static Fragment createFragment(Bundle bundle) {
Fragment fragment = new ViewPagerFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onAttach(Context context) {
tab = getArguments().getString("tab");
Log.d(TAG, "onAttach: "+tab);
super.onAttach(context);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated: " + tab);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: " + tab);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: " + tab);
if(mRootView==null) {
TextView textView = new TextView(container.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
textView.setPadding(25, 25, 25, 25);
textView.setGravity(Gravity.CENTER);
textView.setLayoutParams(params);
textView.setText(tab);
mRootView =textView;
}
return mRootView;
}
}
点击返回键关闭Activity日志输出
01-24 14:29:39.719 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onPause: D
01-24 14:29:39.721 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onPause: E
01-24 14:29:40.567 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onStop: D
onStop: E
01-24 14:29:40.568 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onDestroyView: D
01-24 14:29:40.570 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onDestroy: D
onDetach: D
onDestroyView: E
onDestroy: E
onDetach: E
01-24 14:29:40.571 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onDestroy: A
onDetach: A
onDestroy: B
onDetach: B
onDestroy: C
01-24 14:29:40.572 3087-3087/com.xol.viewpagerfragment D/ViewPagerFragment: onDetach: C
- 当我们关闭Fragment的宿主Activity的时候,此时,所有生成的Fragment都会走 onDestroy-onDetach方法。
总结
我们在结合ViewPager和FragmentPagerAdapter使用的时候,可以在Fragment的OnDestory或OnDetach方法中回收Fragment中的资源。
希望对您有所帮助