Android之Fragment的前世今生
Posted 痕迹天涯119
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android之Fragment的前世今生相关的知识,希望对你有一定的参考价值。
曾经读郭神的《第一行代码》就遇到过fragment(碎片)这个控件,当时觉得应该是为了兼容平板而存在的,书上也特别强调了这一点,后来随着学习的深入,越来越多的地方使用到fragment,好么,我就完整做个总结。
Fargment(碎片)
碎片(Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间
Fragment已经广泛运用到了android开发的各方各面,主要因为其灵活、动态的特点,通过该特点可以很好解决不同分辨率的UI设计问题。甚至可以仅使用一个MainActivity而将其他布局全部采用fragment,此时的代码效率和
Fragment优点:
- Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI。
- Fragment可以轻松得创建动态灵活的UI设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
- Fragment是一个独立的模块,紧紧地与activity绑定在一起。可以运行中动态地移除、加入、交换等。
- Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。
- Fragment 解决Activity间的切换不流畅,轻量切换。
- Fragment 替代TabActivity做导航,性能更好。
- Fragment 在4.2.版本中新增嵌套fragment使用方法,能够生成更好的界面效果。
- Fragment做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragment来代替,只有在需要的时候才加载Fragment,提高性能。
- 可以从startActivityForResult中接收到返回结果,但是View不能。
PS:也许你还不太清楚其中的含义,那么请向下看o(∩_∩)o 哈哈
Activity和Fragment的生命周期对比
Activity生命周期
- onCreate()
在活动第一次被创建的时候调用。主要在这个方法中完成活动的初始化操作,比如说加载布局、绑定事件等。 - onStart()
这个方法在活动由不可见变为可见的时候调用。 - onResume()
这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。 - onPause()
这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。 - onStop()
这个方法在活动完全不可见的时候调用。它和 onPause()方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop()方法并不会执行。 - onDestroy()
这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。 - onRestart()
这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
Fragment生命周期
基本与Activity是一致的,但多出了五个回调方法,如图
- onAttach()
当碎片和活动建立关联的时候调用。 - onCreateView()
为碎片创建视图(加载布局)时调用。 - onActivityCreated()
确保与碎片相关联的活动一定已经创建完毕的时候调用。 - onDestroyView()
当与碎片关联的视图被移除的时候调用。 - onDetach()
当碎片和活动解除关联的时候调用。
Fragment的简单应用
Fragment支持静态和动态的加载,首先来看静态的XML加载方式,Demo图
Fragment的静态加载
添加fragment的布局文件
first_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/firstLayoutBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"/>
</LinearLayout>
second_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/secondLayoutBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Walk the Horizon"/>
</LinearLayout>
静态布局的加载
新建FirstFragment
public class FirstFragment extends Fragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
return inflater.inflate(R.layout.first_layout,container,false);
新建SecondFragment
public class SecondFragment extends Fragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
return inflater.inflate(R.layout.second_layout,container,false);
主布局:
这里特别注意使用了android:name属性关联Fragment类
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<fragment
android:name="com.example.horizon.myapplication.FirstFragment"
android:id="@+id/fragment_first"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<fragment
android:name="com.example.horizon.myapplication.SecondFragment"
android:id="@+id/fragment_second"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
MainActivity代码:
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment的动态加载
动态的加载主要依赖于系统提供的FragmentManger在代码中来完成碎片的自由加载。
去除主布局中的fragment标签,修改主布局代码如下:
public class MainActivity extends AppCompatActivity
FragmentTransaction transaction;
Fragment fragmentFirst;
Fragment fragmentSecond;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentFirst = new FirstFragment();
fragmentSecond = new SecondFragment();
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
//特别注意,同一个事务只能用于一次提交,
// 这里保证每次commit都会有一个新的事务进行支持
transaction = getFragmentManager().beginTransaction();
switch (item.getItemId())
case R.id.add_first:
transaction.add(R.id.mainLayout, fragmentFirst);
break;
case R.id.add_second:
transaction.add(R.id.mainLayout, fragmentSecond);
break;
case R.id.remove_first:
transaction.remove(fragmentFirst);
break;
case R.id.remove_second:
transaction.remove(fragmentSecond);
break;
transaction.commit();
return true;
效果图:
这里务必注意,只能移除当前栈顶的fragment,否则将报错,后面会详细说明。
于是乎,我们完成了Fragment的动态加载,当然很多时候我们使用replace方法进行fragment的加载行为,因为replace=remove+add.
关于本节源码:源码地址
OK,这样就算学会了Fragment的入门使用,后面我会继续深入的对Fragment的使用进行深入的总结和分析。
以上是关于Android之Fragment的前世今生的主要内容,如果未能解决你的问题,请参考以下文章