您的位置:首页 > 移动开发 > Android开发

Android之Fragment的前世今生(一)

2016-05-15 17:26 831 查看
曾经读郭神的《第一行代码》就遇到过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的使用进行深入的总结和分析。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: