夜深了,又到了撸代码的时间,其实一直想把以前学的东西总结一下,看看有哪些疏漏和误解的地方,从这里开始开一个复习系列,当然对于很多刚学习安卓的同学,这应该是一个入门系列。
开始第一章,片段。
为什么是片段而不是活动呢?因为活动的基础回调和基础使用很简单,源码又很难,而且涉及启动模式,状态保存等等,等笔者找到一个能贯穿的平衡点,会单独开一篇活动专题复习。
安卓深入哪一块其实都不简单,所以片段也只讲重点,点到为止。
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中都是这样执行,多动动手总会有收获。