Android温故知新之Fragment篇(一) Fragment生命周期
程序员文章站
2022-06-08 12:13:23
...
夜深了,又到了撸代码的时间,其实一直想把以前学的东西总结一下,看看有哪些疏漏和误解的地方,从这里开始开一个复习系列,当然对于很多刚学习安卓的同学,这应该是一个入门系列。
开始第一章,片段。
为什么是片段而不是活动呢?因为活动的基础回调和基础使用很简单,源码又很难,而且涉及启动模式,状态保存等等,等笔者找到一个能贯穿的平衡点,会单独开一篇活动专题复习。
安卓深入哪一块其实都不简单,所以片段也只讲重点,点到为止。
support.v4.app下的片段具有更好的兼容性,可以兼容到1.6版本,而应用下的片段只支持3.0以上的版本,如果minsdk设置在3.0以上,当然用哪个都可以,如果需要兼容到3.0以下,建议使用V4包下的片段。
划重点1:support.v4.app下的片段可以兼容到1.6版本,且support.v4.app下的片段和应用下的片段不具有继承关系,无法进行类型转换。
笔者以support.v4.app下的片段为例,正式开始今天的学习。
然后创建承载片段的活性:
运行程序,启动时输出如下
开始第一章,片段。
为什么是片段而不是活动呢?因为活动的基础回调和基础使用很简单,源码又很难,而且涉及启动模式,状态保存等等,等笔者找到一个能贯穿的平衡点,会单独开一篇活动专题复习。
安卓深入哪一块其实都不简单,所以片段也只讲重点,点到为止。
初次导入片段时需要选择导哪个包的,有如下两个选择
android.support.v4.app.Fragment
android.app.Fragment;
support.v4.app下的片段具有更好的兼容性,可以兼容到1.6版本,而应用下的片段只支持3.0以上的版本,如果minsdk设置在3.0以上,当然用哪个都可以,如果需要兼容到3.0以下,建议使用V4包下的片段。
划重点1:support.v4.app下的片段可以兼容到1.6版本,且support.v4.app下的片段和应用下的片段不具有继承关系,无法进行类型转换。
笔者以support.v4.app下的片段为例,正式开始今天的学习。
首先创建MyFragment:
MyFragment.java
public class MyFragment extends Fragment {
private static final String TAG =“MyFragment--”;
@Override
public void onInflate(Context context,AttributeSet attrs,Bundle savedInstanceState){
super.onInflate(context,attrs,savedInstanceState);
Log.d(TAG,“onInflate:执行”);
}
@Override
public void onAttach(Context context){
super.onAttach(context);
Log.d(TAG,“onAttach:执行”);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: 执行");
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: 执行");
View view = inflater.inflate(R.layout.fragment_my,container,false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated: 执行");
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart: 执行");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume: 执行");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause: 执行");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop: 执行");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView: 执行");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: 执行");
}
@Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach: 执行");
}
}
fragment_my.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width = “match_parent”
android:layout_height = “match_parent”
android:text= “fragment”/>
</RelativeLayout>
然后创建承载片段的活性:
MyActivity.java
public MyActivity extends AppCompatActivity {
private static final String TAG =“MyActivity ++”;
@Override
protected onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate:执行");
Log.d(TAG,"setContentView:执行前");
setContentView(R.layout.activity_my);
Log.d(TAG,"setContentView:执行后");
}
@Override
protected onStart(){
super.onStart();
Log.d(TAG,"onStart:执行");
}
@Override
protected onStop(){
super.onStop();
Log.d(TAG,"onStop:执行");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: 执行");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: 执行");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: 执行");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart: 执行");
}
}
activity_my.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tustcs.ndktest.MyActivity">
<fragment
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:id = "@+id/my_fragment"
class= "com.tustcs.ndktest.MyFragment"/>
</RelativeLayout>
运行程序,启动时输出如下
可以发现,onInflate,onAttach,的onCreate,onCreateView,onActivityCreated这四个方法都发生在给活动设置视图的时候,在onStart,的onResume分别与活动的调用onStart,的onResume对应。
点击回键后,销毁过程如下销毁过程中片段的的onPause,的onStop分别和活动的的onPause,的onStop相对应,onDestroyView,onDestory,onDetach发生在活动的的onDestroy方法中。并且和活性一样,片段的生命周期方法也是成对出现的,按什么顺序创建就按它的逆序销毁。
我们又可以搬出那张经典的图:
没错,这里少了onInflate方法,onInflate只有在通过<片段>标签添加片段时才会调用。
public void onInflate(上下文上下文,AttributeSet attrs,Bundle savedInstanceState)
注意onInflate的第二个参数和第三个参数,熟悉自定义视图的人对AttrbuteSet一定非常熟悉,这是搜索获取XML值的关键,所以在其方法内,可以读取到其XML中的属性值,通过第三个参数可以保存状态。
通过
public class MyActivity extends AppCompatActivity {
private static final String TAG = "MyActivity++";
private MyFragment myFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: 执行");
super.onCreate(savedInstanceState);
Log.d(TAG, "setContentView: 执行前");
setContentView(R.layout.activity_my);
Log.d(TAG, "setContentView: 执行后");
myFragment = new MyFragment();
android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(myFragment,"aaa");
ft.commit();
}
运行结果如下:
动态添加Fragment不会调用onInflate。
至于为什么一张图就能总结的东西,笔者还是敲了一堆代码去验证,或许这就是计算机的学习之路,实践出真知,就像笔者曾在一本书中介绍说Fragment的onInflate会在Activity的onCreate之前调用,经过亲自验证才发现并不是如此,至少不在所有版本的SDK中都是这样执行,多动动手总会有收获。