Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

生命周期

标准的生命周期

当创建、显示Fragment的时候都是先执行Activity的方法,当停止、销毁Fragment的时候都是先执行Fragment的方法。

皮之不存,毛将焉附!

Activity【onCreate】//Activity的onCreate是一切的起点
【onAttach】null
【onCreate】微信
【onCreateView】微信
【onViewCreated】
【onActivityCreated】微信 【onStart】微信
Activity【onStart】
Activity【onResume】
【onResume】微信 【onPause】微信
Activity【onPause】
【onStop】微信
Activity【onStop】 【onDestroyView】微信
【onDestroy】微信
【onDetach】微信
Activity【onDestroy】//Activity的onDestroy是一切的终点

创建时的逻辑

  • 先调用onAttach,表明将Fragment添加到了Activity;onAttach会回调给我们一个Context对象,一般此Context就是此Fragment所依附的那个Activity;不过一般我们不重写此方法而是重写onCreate方法
  • 再调用onCreate,表明开始创建Fragment了,注意此方法只会调用一次,类似于Activity的onCreate只会调用一次;同样类似于Activity的onCreate方法,此方法会回调给我们一个 Bundle savedInstanceState 对象,用于状态的恢复,我们一般在这里做初始化操作(而不是在onAttach中)
  • 再调用onCreateView,表明开始创建Fragment中的View了,此方法是Fragment中最常操作的一个方法,因为我们必须在此方法中返回Fragment所需的View,通常我们直接在这里执行 inflateView 及 findView 甚至包括 initView 操作
  • 再调用onViewCreated,表明Fragment中的View已经创建完成了,此时可以根据参数view初始化View了
  • 最后调用onActivityCreated,表明Activity的onCreate方法执行完毕了,只有在这及之后,Fragment才能和Activity进行交互

销毁时的逻辑

  • 先调用onDestroyView,把Fragment的View销毁掉,此方法和onCreateView是相对应的
  • 再调用onDestroy,把Fragment的自身销毁掉,此方法只会调用一次;此方法类似于Activity的onDestroy方法,一般在这里做内存释放、资源的回收等操作
  • 最后调用onDetach,把Fragment从Activity中移除

与事务相关的生命周期

hide、show方法

  • 如果通过hide方法将此Fragment隐藏掉,即使此时Fragment对用户不可见,但是因为Fragment是依附于Activity的,当Activity通过前后台切换等方式回调onStart、onResume、onPause、onStop等方法时,仍会回调Fragment的onStart、onResume、onPause、onStop方法。并且如果FragmentManager管理有多个Fragment,那么所有这些Fragment都会回调onStart、onResume、onPause、onStop方法。

  • 同样,如果Activity没有回调onStart、onResume、onPause、onStop等方法,即使你通过hide方法将此Fragment隐藏了,或者通过show方法将此Fragment显示了,虽然Fragment的可见状态改变了,但是所有这些Fragment都仍然不会回调onStart、onResume、onPause、onStop方法。

简单来说就是,使用show或hide显示或隐藏Fragment时,Fragment的生命周期不会发生任何变化。

add、remove方法

  • 上面说的只是hideshow方法,如果你用的是addremove方法,则Fragment的生命周期是会相应回调的。

  • 比如你在Activity的中通过点击一个按钮将一个Fragment通过add方式添加到Activity中,其会依次回调onAttach、onCreate、onCreateView、onViewCreated、onActivityCreated、onStart、onResume方法。此时你再通过remove方法将其移除时,则会依次回调onPause、onStop、onDestroyView、onDestroy、onDetach方法。

简单来说就是,使用add或remove添加或移除Fragment时,Fragment的生命周期会发生任何变化。

replace方式显示Fragment,不添加到回退栈

  • 当我们通过replace()方式首次展示FragA时,它的生命周期展示方式是同在布局文件中静态设置的表现一模一样的。
  • 在我们正常展示FragA且没有addToBackStack后,通过replace方式用另一个FragmentB替换掉FragA时,FragA调用顺序为onPause, onStop, onDestroyView, onDestroy, onDetach。这说明,FragA已经被FragmentManager完全抛弃了,取而代之的是FragB的完全展现。
  • 如果此时按返回键的话,FragB的生命周期也将是onPause, onStop, onDestroyView, onDestroy, onDetach。这说明,在添加FragmentA时,如果没有调用addToBackStack的话,当FragmentManager以【replace】方式更换掉此FragmentA时,是不会保存被更换掉的FragmentA的状态的。

replace方式显示Fragment,添加到回退栈

  • 我们首先通过replace()方式正常添加FragA,并addToBackStack,同样,它的生命周期展示方式是同在布局文件中静态设置的表现一模一样的。
  • 然后我们用FragB来替换FragA,并addToBackStack,此时FragA生命周期方法只是调用到了onDestroyView,而onDestroy和onDetach则没有被调用。这说明FragA的View被销毁了,但是FragmentManager并没有完全销毁FragA,FragA的状态被保存在FragmentManager里面。
  • 然后再使用FragA来替换当前显示的FragB,此时FragB的生命方法调用顺序是跟FragB替换FragA时FragA的调用顺序一致的。而此时FragA的调用则值得注意。此时FragA直接从onCreateView调起,也就是说只是重新创建了视图,而依然使用上次被替换时的Fragment状态。
  • 此时(每次替换时都addToBackStack)按BACK返回时,界面是由FragA-->FragB,即销毁FragA的【视图】,重建FragB的【视图】
  • 再按BACK返回时,界面由FragB-->FragA,由于回退栈中没有FragB了,所以这时会完全【销毁FragB】,并重建FragA的【视图】
  • 再按BACK返回时,Fragment界面消失,但Activity不消失,由于回退栈中也没有FragA了,所以这时会完全【销毁FragA】
  • 再按BACK返回时,【Activity】界面才会完全退出。

为什么 add 之前需要判断是否为null

因为当【Activity】因为配置发生改变(如屏幕旋转)或者因内存不足被系统杀死,造成被重新创建时,我们的【Fragment】会被保存下来

而当【Activity】被重建时【FragmentManager】会自动获取保存下来的【Fragment】队列并重建Fragment队列,从而可以恢复之前的状态

所以如果不判断指定id的Fragment是否为null就add,会造成在同一id下有多个Fragment的情况(多个Fragment会重叠在一起)

需要注意的是,因为FragmentManager重建【Fragment】时调用的是Fragment的无参的构造方法,如果不存在无参的构造方法(比如定义了有参的构造方法后没有再显示的定义无参的构造方法),那么会导致异常,这时整个Activity就崩溃了。

同时还需要注意的是,如果定义了有参的构造方法后又定义了无参的构造方法,那么由于重建Fragment时,调用的是Fragment的无参的构造方法,所以此Fragment会由于缺少必要的参数而导致显示数据异常。

所以,强烈不建议给Fragment定义有参的构造方法,如果需要传数据过来,就通过setArguments传递。

测试事务相关的生命周期的案例

public class MainActivity2 extends FragmentActivity {
private static final String TAG1 = "normal_mode", TAG2 = "replace_mode";
private TextView tvTitle, tvWeixin, tvFriend, tvContact, tvSetting;
private String[] titles = {"add", "hide", "show", "remove"};
private FragmentManager fragmentManager;
private Fragment fragment1, fragment2; boolean replaceMode = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView(); fragmentManager = getSupportFragmentManager();
fragment1 = fragmentManager.findFragmentByTag(TAG1);//这一步是必须要的,否则横竖屏切换时会重复创建Fragment
fragment2 = fragmentManager.findFragmentByTag(TAG2);
if (fragment1 == null) fragment1 = MyFragment.newInstance("第一个");
if (fragment2 == null) fragment2 = MyFragment.newInstance("第二个");
} private void initView() {
tvWeixin = findViewById(R.id.tv_tab_bottom_weixin);
tvFriend = findViewById(R.id.tv_tab_bottom_friend);
tvContact = findViewById(R.id.tv_tab_bottom_contact);
tvSetting = findViewById(R.id.tv_tab_bottom_setting); tvWeixin.setTag(0);
tvFriend.setTag(1);
tvContact.setTag(2);
tvSetting.setTag(3); tvWeixin.setOnClickListener(v -> reset((Integer) v.getTag()));
tvFriend.setOnClickListener(v -> reset((Integer) v.getTag()));
tvContact.setOnClickListener(v -> reset((Integer) v.getTag()));
tvSetting.setOnClickListener(v -> reset((Integer) v.getTag())); tvTitle = findViewById(R.id.tv_title);
tvTitle.setText(replaceMode ? "replace模式" : "非replace模式");
tvTitle.setOnClickListener(v -> {
replaceMode = !replaceMode;
tvTitle.setText(replaceMode ? "replace模式" : "非replace模式");
Log.i("bqt", "【Fragment数量】" + fragmentManager.getFragments().size());
});
} private void reset(int position) {
tvWeixin.setSelected(position == 0);
tvFriend.setSelected(position == 1);
tvContact.setSelected(position == 2);
tvSetting.setSelected(position == 3); switch (position) {
case 0:
if (fragmentManager.findFragmentById(R.id.id_container) == null) {
//在一个activity上重复add同一个Fragment会崩溃,然而可以在一个id上add多个不同的Fragment,但这样后面的会把前面的盖住
fragmentManager.beginTransaction().add(R.id.id_container, fragment1, TAG1).commit();
}
break;
case 1:
//没有add或在remove后调用hide、show方法不会异常,且只会在第一次调用时回调onAttach和onCreate方法
if (!replaceMode) fragmentManager.beginTransaction().hide(fragment1).commit();
else fragmentManager.beginTransaction().replace(R.id.id_container, fragment1, TAG1).addToBackStack("name").commit();
break;
case 2:
if (!replaceMode) fragmentManager.beginTransaction().show(fragment1).commit();
else fragmentManager.beginTransaction().replace(R.id.id_container, fragment2, TAG2).commit();
break;
case 3:
//没有add就调用remove方法不会异常,且不会回调任何方法,且再调用hide、show方法也不会回调任何方法
if (!replaceMode) fragmentManager.beginTransaction().remove(fragment1).commit();
else fragmentManager.beginTransaction().replace(R.id.id_container, fragment2, TAG2).addToBackStack("name").commit();
break;
default:
break;
}
}
}

FragmentTransaction

全部方法

FragmentTransaction 的全部方法(API 24):

  • add(Fragment fragment, String tag) // 调用add(int, Fragment, String),填入为0的containerViewId.
  • add(int containerViewId, Fragment fragment) // 调用add(int, Fragment, String),填入为null的tag.
  • add(int containerViewId, Fragment fragment, String tag) // 向Activity中添加一个Fragment.
  • addSharedElement(View sharedElement, String name) // 添加共享元素
  • addToBackStack(String name) // 将事务添加到回退栈
  • attach(Fragment fragment) // 重新关联Fragment(当Fragment被detach时)
  • commit() // 提交事务
  • commitAllowingStateLoss() // 类似commit(),但允许在Activity状态保存之后提交(即允许状态丢失)。
  • commitNow() // 同步提交事务
  • commitNowAllowingStateLoss() // 类似commitNow(),但允许在Activity状态保存之后提交(即允许状态丢失)。
  • detach(Fragment fragment) // 将fragment保存的界面从UI中移除
  • disallowAddToBackStack() // 不允许调用addToBackStack(String)操作
  • hide(Fragment fragment) // 隐藏已存在的Fragment
  • isAddToBackStackAllowed() // 是否允许添加到回退栈
  • isEmpty() // 事务是否未包含的任何操作
  • remove(Fragment fragment) // 移除一个已存在的Fragment
  • replace(int containerViewId, Fragment fragment) // 调用replace(int, Fragment, String)填入为null的tag.
  • replace(int containerViewId, Fragment fragment, String tag) // 替换已存在的Fragment
  • setBreadCrumbShortTitle(int res) // 为事务设置一个BreadCrumb短标题
  • setBreadCrumbShortTitle(CharSequence text) // 为事务设置一个BreadCrumb短标题,将会被FragmentBreadCrumbs使用
  • setBreadCrumbTitle(int res) // 为事务设置一个BreadCrumb全标题,将会被FragmentBreadCrumbs使用
  • setBreadCrumbTitle(CharSequence text) // 为事务设置一个BreadCrumb全标题
  • setCustomAnimations(int enter, int exit, int popEnter, int popExit) // 自定义事务进入/退出以及入栈/出栈的动画效果
  • setCustomAnimations(int enter, int exit) // 自定义事务进入/退出的动画效果
  • setTransition(int transit) // 为事务设置一个标准动画
  • setTransitionStyle(int styleRes) // 为事务标准动画设置自定义样式
  • show(Fragment fragment) // 显示一个被隐藏的Fragment

几个常用API的区别

比如,我在FragmentA中的EditText填了一些数据,当切换到FragmentB后又切换回FragmentA时:

  • 如果希望回到A时还能看到以前数据,则适合你的就是hide和show
  • 如果你希望回到A时看到的是全新的数据,则可以优先使用detach和attach,这样会只重建视图而不重建Fragment
  • 而如果希望回到A时是重新创建的全新的Fragment,则你可以使用replace(即remove+ add),在Fragment比较多时这种方式是合理的,因为不需要的Fragment都被销毁了

添加移除显示隐藏方法

add

往Activity中添加一个Fragment

API文档

add(Fragment fragment, String tag);
add(int containerViewId, Fragment fragment)
add(int containerViewId, Fragment fragment, String tag)

Add a fragment to the activity state. This fragment may optionally also have its view (if Fragment.onCreateView returns non-null) inserted into a container view of the activity.

参数:

  • containerViewId:Optional identifier of the container this fragment is to be placed in. If 0, it will not be placed in a container.
  • fragment:The fragment to be added. This fragment must not already be added to the activity.
  • tag Optional tag name for the fragment, to later retrieve the fragment with FragmentManager.findFragmentByTag(String).

参数containerViewId一般会传Activity中某个视图容器的id,如果containerViewId传0,则这个Fragment不会被放置在一个容器中,但不要认为Fragment没添加进来,只是我们添加了一个没有视图的Fragment,这个Fragment可以用来做一些类似于service的后台工作。

在一个activity上重复add同一个Fragment会崩溃,然而可以在一个id上add多个不同的Fragment,但这样后面的会把前面的盖住

Fragment被重复添加的问题

下面看一个使用add方法添加Fragment的坑:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager.beginTransaction().add(R.id.fl_main, new MyFragment(), "tag").commit();
findViewById(R.id.fl_main).setOnClickListener(v -> Log.i("bqt", "【Fragment数量】" + fragmentManager.getFragments().size()));
}

接下来运行一下程序,我们进行几次横竖屏切换,并且每次切换都点击下布局容器,我们发现Activity里的Fragment数量在不断的增加。

其实,当我们Activty被异常销毁时,Activity会对自身状态进行保存,这里面包含了我们添加的Fragment。在Activity被重新创建时,又对我们之前保存的Fragment进行了恢复,但是我们在onCreate时却又添加了1次Fragment,所以我们的Fragment数量在不断增加...

添加Fragment的正确方式

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if(fragmentManager.findFragmentById(R.id.fl_main) == null) { //也可以用 findFragmentByTag
fragmentManager.beginTransaction().add(R.id.fl_main, new MyFragment(), "tag").commit();
}
}
}

remove

从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。

remove(Fragment fragment)

Remove an existing fragment. If it was added to a container, its view is also removed from that container.

Fragment被remove后,Fragment的生命周期会一直执行完onDetach,之后Fragment的实例也会从FragmentManager中移除。

replace

使用另一个Fragment替换当前的Fragment,实际上就是 remove(所有旧的) + add(一个新的)

replace(int containerViewId, Fragment fragment)
replace(int containerViewId, Fragment fragment, String tag)

Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

show 和 hide

显示一个以前被隐藏过的Fragment,或隐藏一个存在的Fragment

Shows a previously以前 hidden fragment. This is only relevant适用于 for fragments whose views have been added to a container, as this will cause the view to be shown.

show(Fragment fragment) //显示之前隐藏的Fragment

Hides an existing fragment. This is only relevant for fragments whose views have been added to a container, as this will cause the view to be hidden.

hide(Fragment fragment) //隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

Fragment被 hide/show,仅仅是隐藏/显示Fragment的视图,不会有任何生命周期方法的调用。

在Fragment中重写onHiddenChanged方法可以对Fragment的hide和show状态进行监听。

attach 和 detach

重建Fragment的view视图,或将Fragment的view视图从UI中移除

Re-attach关联 a fragment after it had previously been detached from the UI with detach(Fragment). This causes its view hierarchy to be re-created, attached to the UI, and displayed.

attach(Fragment fragment)

Detach the given fragment from the UI. This is the same state as when it is put on the back stack: the fragment is removed from the UI, however its state is still being actively managed by the fragment manager. When going into this state its view hierarchy is destroyed.

detach(Fragment fragment) //和remove()不同,detach后fragment的状态依然由FragmentManager维护

当Fragment被detach后,Fragment的生命周期执行完onDestroyView就终止了,这意味着Fragment的实例并没有被销毁,只是UI界面被移除了(注意和remove是有区别的)。

当Fragment被detach后,执行attach操作,会让Fragment从onCreateView开始执行,一直执行到onResume。

attach无法像add一样单独使用,单独使用会抛异常。方法存在的意义是对detach后的Fragment进行界面恢复。

addToBackStack

记录已提交的事务,可用于回退操作。

addToBackStack(String name) //An optional name for this back stack state, or null.

Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.

将此事务添加到后台堆栈。这意味着该事务被提交后将会被记住后,回退操作后,事务会从堆栈中弹出。

addToBackStack适用于remove、hide、show、attach、detach等所有操作。

Fragment回退栈类似于Android系统为Activity维护的任务栈,如果你将Fragment添加到回退栈中,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键时,才退出当前Activity。

add并addToBackStack后,第1次按下手机的back键,程序没有退出而是变成了白板(其实是回退了之前的add操作,相当于没有添加Fragment),第2次按下手机的back键,因为当前回退栈已空,程序就直接退出了。

commit 系列方法

提交一个事务

commit() //安排一个事务的提交,一定要在Activity.onSaveInstance()之前调用
commitAllowingStateLoss() //和commit一样,但是允许Activity的状态保存之后提交
commitNow() //同步的提交这个事务,API_24添加
commitNowAllowingStateLoss() //和commitNow()一样,但是允许Activity的状态保存之后提交,API_24添加的

commit():安排一个针对该事务的提交。提交并没有立刻发生,会安排到在主线程下次准备好的时候来执行。

commitNow():同步的提交这个事务。任何被添加的Fragment都将会被初始化,并将他们完全带入他们的生命周期状态。

使用commitNow()类似于先调用commit()方法,之后调通FragmentManager的 executePendingTransactions() 方法,但commitNow()比后者的这种操作更好,后者在尝试提交当前事务时会有副作用(具体的副作用是什么,API文档没有给出说明)。

使用commitNow()时不能进行添加回退栈的操作,否则会抛出一个 IllegalStateException的异常。

如果调用 Transaction 的 commit 方法时抛出Can not perform this action after onSaveInstanceState异常,可以改成使用 commitAllowingStateLoss 方法:

选择正确的 commitXXX 函数

setCustomAnimations

为Fragment的进入/退出设置指定的动画资源。

setCustomAnimations(int enter, int exit)
setCustomAnimations(int enter, int exit, int popEnter, int popExit)

该方法用于给Fragment设置自定义切换动画。四个参数方法的后两个参数也是传入指定动画资源,在某个事务被addToBackStack或回退时起动画效果。

getSupportFragmentManager不支持属性动画,仅支持补间动画。getFragmentManager支持属性动画。

使用setCustomAnimations一定要放在add、remove...等操作之前。

addSharedElement

用于将View从一个被删除的或隐藏的Fragment映射到另一个显示或添加的Fragment上。

addSharedElement(View sharedElement, String name)

方法作用:设置共享元素(或着说共享View),第二个参数name是这个共享元素的标识。

使用SharedElement切换Fragment页面

主界面 Tab + Fragment 实现案例

实现效果类似于 ViewPage + Fragment 的组合,主要用到了Transaction的add、show、hide等方法。

Activity

public class MainActivity extends FragmentActivity {
private TextView tvTitle, tvWeixin, tvFriend, tvContact, tvSetting;
private String[] titles = {"微信", "通讯录", "发现", "我"};
private FragmentManager fragmentManager;
private Fragment weixinFragment, friendFragment, contactFragment, settingFragment;
private int selectPosition = -1;//默认值不能设为0、1、2、3 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
reset(0);
} private void initView() {
tvWeixin = findViewById(R.id.tv_tab_bottom_weixin);
tvFriend = findViewById(R.id.tv_tab_bottom_friend);
tvContact = findViewById(R.id.tv_tab_bottom_contact);
tvSetting = findViewById(R.id.tv_tab_bottom_setting); tvWeixin.setTag(0);
tvFriend.setTag(1);
tvContact.setTag(2);
tvSetting.setTag(3); tvWeixin.setOnClickListener(v -> reset((Integer) v.getTag()));
tvFriend.setOnClickListener(v -> reset((Integer) v.getTag()));
tvContact.setOnClickListener(v -> reset((Integer) v.getTag()));
tvSetting.setOnClickListener(v -> reset((Integer) v.getTag())); tvTitle = findViewById(R.id.tv_title);
tvTitle.setOnClickListener(v -> Log.i("bqt", "【Fragment数量】" + fragmentManager.getFragments().size())); fragmentManager = getSupportFragmentManager();
weixinFragment = fragmentManager.findFragmentByTag(titles[0]);//这一步是必须要的,否则横竖屏切换时会重复创建Fragment
friendFragment = fragmentManager.findFragmentByTag(titles[1]);
contactFragment = fragmentManager.findFragmentByTag(titles[2]);
settingFragment = fragmentManager.findFragmentByTag(titles[3]);
} private void reset(int position) {
tvWeixin.setSelected(position == 0);
tvFriend.setSelected(position == 1);
tvContact.setSelected(position == 2);
tvSetting.setSelected(position == 3); if (position != selectPosition) {
tvTitle.setText(titles[position]);
hideFragment();//隐藏掉选中之前正在显示的Fragment
showFragment(position);//显示当前选中的Fragment
selectPosition = position;//更新当前选中的Fragment
}
} private void showFragment(int position) {
switch (position) {
case 0:
if (weixinFragment == null) {
weixinFragment = MyFragment.newInstance(titles[position]);
fragmentManager.beginTransaction().add(R.id.id_container, weixinFragment, titles[position]).commit();//设置tag,方便获取
} else {
fragmentManager.beginTransaction().show(weixinFragment).commit();//使用之前要保证不为空并且目前是否隐藏状态
}
break;
case 1:
if (friendFragment == null) {
friendFragment = MyFragment.newInstance(titles[position]);
fragmentManager.beginTransaction().add(R.id.id_container, friendFragment, titles[position]).commit();
} else {
fragmentManager.beginTransaction().show(friendFragment).commit();
}
break;
case 2:
if (contactFragment == null) {
contactFragment = MyFragment.newInstance(titles[position]);
fragmentManager.beginTransaction().add(R.id.id_container, contactFragment, titles[position]).commit();
} else {
fragmentManager.beginTransaction().show(contactFragment).commit();
}
break;
case 3:
if (settingFragment == null) {
settingFragment = MyFragment.newInstance(titles[position]);
fragmentManager.beginTransaction().add(R.id.id_container, settingFragment, titles[position]).commit();
} else {
fragmentManager.beginTransaction().show(settingFragment).commit();
}
break;
default:
break;
}
} private void hideFragment() {
switch (selectPosition) {
case 0:
fragmentManager.beginTransaction().hide(weixinFragment).commit();
break;
case 1:
fragmentManager.beginTransaction().hide(friendFragment).commit();
break;
case 2:
fragmentManager.beginTransaction().hide(contactFragment).commit();
break;
case 3:
fragmentManager.beginTransaction().hide(settingFragment).commit();
break;
default:
break;
}
}
}

Fragment

public class MyFragment extends Fragment {
private String name;
public static final String ARGUMENT = "name"; public static MyFragment newInstance(String name) {
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putString(ARGUMENT, name);
fragment.setArguments(bundle);
return fragment;
} @Override
public void onAttach(Context context) {
super.onAttach(context);
Log.i("bqt", "【onAttach】" + name);//在这里获取Bundle中的数据也是可以的,不过都在onCreate做初始化操作
} @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
name = bundle != null ? bundle.getString(ARGUMENT) : "unknown";
Log.i("bqt", "【onCreate】" + name);
} @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("bqt", "【onCreateView】" + name);
View rootView = inflater.inflate(R.layout.fragment_tab, container, false);
TextView tv = rootView.findViewById(R.id.tv);
tv.setText(name + ":" + new SimpleDateFormat("HH:mm:ss SSS", Locale.getDefault()).format(new Date()));
tv.setBackgroundColor(0xFF000000 + new Random().nextInt(0xFFFFFF));
return rootView;
} @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i("bqt", "【onViewCreated】");
} @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i("bqt", "【onActivityCreated】" + name);
} @Override
public void onStart() {
super.onStart();
Log.i("bqt", "【onStart】" + name);
} @Override
public void onResume() {
super.onResume();
Log.i("bqt", "【onResume】" + name);
} @Override
public void onPause() {
super.onPause();
Log.i("bqt", "【onPause】" + name);
} @Override
public void onStop() {
super.onStop();
Log.i("bqt", "【onStop】" + name);
} @Override
public void onDestroyView() {
super.onDestroyView();
Log.i("bqt", "【onDestroyView】" + name);
} @Override
public void onDestroy() {
super.onDestroy();
Log.i("bqt", "【onDestroy】" + name);
} @Override
public void onDetach() {
super.onDetach();
Log.i("bqt", "【onDetach】" + name);
}
}

布局

<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:id="@+id/tv_title"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:gravity="center"
android:text="微信"
android:textColor="#000"
android:textSize="20sp"
android:textStyle="bold"/> <View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#dbdbdb"/> <FrameLayout
android:id="@+id/id_container"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2016"/> <View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#dbdbdb"/> <LinearLayout
android:id="@+id/ly_main_tab_bottom"
android:layout_width="fill_parent"
android:layout_height="55dp"> <TextView
android:id="@+id/tv_tab_bottom_weixin"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="微信"
android:textColor="@drawable/text_color_sel"/> <TextView
android:id="@+id/tv_tab_bottom_friend"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="通讯录"
android:textColor="@drawable/text_color_sel"/> <TextView
android:id="@+id/tv_tab_bottom_contact"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="发现"
android:textColor="@drawable/text_color_sel"/> <TextView
android:id="@+id/tv_tab_bottom_setting"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="我"
android:textColor="@drawable/text_color_sel"/>
</LinearLayout> </LinearLayout>

2019-3-28

Fragment 生命周期 事务 MD的更多相关文章

  1. Android Fragment 生命周期及其API使用(建议使用自定义View替换Fragment)

    我为什么不主张使用Fragment Fragment:( Fragment就相当于一个有生命周期的View,它的生命周期被所在的Activity的生命周期管理 ) 生命周期回调说明: onAttach ...

  2. Android Fragment 生命周期及其正确使用(建议使用自定义View替换Fragment)

    使用Fragment 官方例子中显示: 例如:一个学生Fragment,需要传入studentId,进行http请求显示,那么setArguments后防止杀掉Fragment后,参数为0,显示不了数 ...

  3. 【Android开发】之Fragment生命周期

    上一篇博客我们讲到了,Fragment的基本使用,相信大家都已经了解怎么去使用了.如果还有不懂得同学可以去看一下,传送门.现在我们来讲解一下Fragment的生命周期. 一.Fragment的事务 再 ...

  4. Android中Fragment生命周期和基本用法

    1.基本概念 1. Fragment是什么? Fragment是可以让你的app纵享丝滑的设计,如果你的app想在现在基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fra ...

  5. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  6. Android之Fragment学习笔记②(Fragment生命周期)

    一. Fragment生命周期图                                  二.Fragment生命周期方法介绍 Fragment的生命周期和activity生命周期很像,其生 ...

  7. Android Activity生命周期以及Fragment生命周期的区别与分析

    Android Fragment生命周期图: Activity生命周期图: 对照图: Fragment生命周期分析: 1. 当一个fragment被创建的时候,它会经历以下状态. onAttach() ...

  8. Fragment(四)Fragment生命周期分析(转)

    Fragment(四)Fragment生命周期分析 转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/24271607   例子一 ...

  9. Fragment生命周期与Fragment执行hide、show后的生命周期探讨

    一.Fragment 生命周期中的每个方法的意义与作用: 1.setUserVisibleHint()(此方法不属于生命周期方法):设置Fragment 用户可见或不可见时调用此方法,此方法在Frag ...

随机推荐

  1. ref:一系列用于Fuzzing学习的资源汇总

    ref:http://www.freebuf.com/articles/rookie/169413.html 一系列用于Fuzzing学习的资源汇总 secist2018-04-30共185833人围 ...

  2. 图解安装CLion编写程序并进行单元测试

    我对JetBrains公司的IDE情有独钟,于是这里使用的IDE是CLion,CLion是以IntelliJ为基础,专为开发C及C++所设计的跨平台IDE,可以在Windows.Linux及MacOS ...

  3. 洛谷P4782 【模板】2-SAT问题 [2-SAT]

    题目传送门 [模板]2-SAT问题 题目背景 2-SAT 问题 模板 题目描述 有n个布尔变量 $x_1/~x_n$​ ,另有$m$个需要满足的条件,每个条件的形式都是“ $x_i$ 为$true/f ...

  4. redis:CLUSTER cluster is down 解决方法

    redis:CLUSTER cluster is down 解决方法 首先进入安装目录的src下: 1. ./redis-trib.rb check 127.0.0.1:7001 检查问题所在 2.  ...

  5. android bitmap recycle

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 不需要位图的时候,就可以手动调用recycle. 2.3之前 位图对象 存在 java的 ...

  6. 前缀和:CodeForces 932B Recursive Queries

    Description Let us define two functions f and g on positive integer numbers. You need to process Q q ...

  7. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  8. Problem E: 深入浅出学算法006-求不定方程的所有解

    Description 现有一方程ax+by=c,其中系数a.b.c均为整数,求符合条件的所有正整数解,要求按x由小到大排列,其中a b c 均为不大于1000的正整数 Input 多组测试数据,第一 ...

  9. 【8.31校内测试】【找规律二分】【DP】【背包+spfa】

    打表出奇迹!表打出来发现了神奇的规律: 1 1 2 2 3 4 4 4 5 6 6 7 8 8 8 8 9 10 10 11 12 12 12 13 14 14 15 16 16 16 16 16.. ...

  10. [转]Java 对象锁-synchronized()与线程的状态与生命周期

      线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){   //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...