Fragment是我们Android中很常用的一种ui,它是一种依赖在Activity中,但又和Activity有些相像,同样拥有生命周期,使用率也很高,可以动态、灵活的加载到Activity中。
Fragment的生命周期:
onAttach() 与Activity连接--------Fragment
onCrete()
onCreteView()
onActivityCreate()
| onCreate() --------Activity
onActivityCreate()
| onStart() --------Activity
onStart()
| onReume() --------Activity
onResume() ------------ Fragemnt初始化
onPause()
| onPause() --------Activity
onStop()
| onStop() --------Activity
onDestoryView()
onDestory()
onDeath() ------------ Fragemnt销毁
| onDestory() --------Activity
Fragment创建:
- 静态:这是使用Fragment最简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中,用布局文件调用Fragment
- 继承Fragment,重写onCreateView决定Fragment布局。
- 在Activity中声明此Fragment,就当和普通的View一样。
<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">
<fragment
android:name="com.example.TitleFragment"
android:id="@+id/title"
android:layout_height="45dp"
android:layout_width="match_parent"/>
<fragment
android:layout_below="@id/title"
android:name="com.example.ContentFragment"
android:id="@+id/content"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
</RelativeLayout>
public class ContentFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.content_fragment, container,false);
}
}
- 动态:动态使用fragment是最简单的方式,下面介绍如何动态的添加、更新、以及删除Fragment
- 为了动态使用Fragment,我们修改一下Actvity的布局文件,中间使用一个FrameLayout
- 首先是将上面的布局文件通过setContentView()加载进来.然后通过代码把Fragment添加到FrameLayout中
<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" >
<FrameLayout
android:id="@+id/id_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
这里我们有一个方法: transaction.addTobackStack(null);这个方法可以接受一个名字表述返回栈的效果。
public class MainActivity extends FragmentActivity{
private ContentFragment exampleFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
@SuppressLint("NewApi")
private void setDefaultFragment() {
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
exampleFragment= new ContentFragment();
transaction.replace(R.id.id_content, exampleFragment);
transaction.addTobackStack(null);//将事务添加到返回栈效果
transaction.commit();
}
}
Fragment常用方法:
Fragment常用的三个类:
- android.app.Fragment 主要用于定义Fragment
- android.app.FragmentManager 主要用于在Activity中操作Fragment
- android.app.FragmentTransaction 保证一些列Fragment操作的原子性
获取FragmentManage的方式:
- getFragmentManager()
- getSupportFragmentManager()
- getChildFragmentManager()
FragmentTransaction的方法:
开启一个事务: FragmentTransaction transaction = fm.benginTransatcion();
- transaction.add()
往Activity中添加一个Fragment - transaction.remove()
从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。 - transaction.replace()
使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体 - transaction.hide()
隐藏当前的Fragment,仅仅是设为不可见,并不会销毁, - transaction.show()
显示之前隐藏的Fragment
- detach()
会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。 - attach()
重建view视图,附加到UI上并显示。 - transatcion.commit()
提交一个事务
主要使用Fragment 框架搭配就是 Fragment+viewPager,那么这里就有一个问题:
使用这个搭配,就要进行适配,那么有FragmentpagerAdapter和FragmentStagepagerAdapter,那哪一种性能更加好呢。
我们分别可以看他们的底层原码:
FragmentStagepagerAdapter:
FragmentpagerAdapter:
可以得到结论:FragmentpagerAdapter只是ui分离 ,而FragmentStagepagerAdapter切换时,回收内存,完全删除不用的资源
Fragment 的懒加载如何实现呢?
1.Viewpager 的每一个Fragment都需要通过网络拉去数据加载,ViewPager是默认加载前两项,很容易造成丢包的现象,所以懒加载是非常必要的。
2.那么在Fragment中,有一个方法是setUserVisibleHint();他由于onCreate方法,如果这个方法为true,那就说明Fragment可见,若为true就是懒加载
Fragment的通信方案
参考:https://www.jianshu.com/p/1b824e26105b
Activity与Fragment之间是存在依赖关系的,因此它们之间必然会涉及到通信问题,解决通信问题必然会涉及到对象之间的引用。因为Fragment的出现了一个重要的使命就是:模块化,从而提高复用性。若达到此效果,Fragment必须做到高内聚,低耦合。
目前能想到的解决它们之间通信的方案有:handler,广播,EvnetBus,setArguments,接口等
接口:既能达到复用,又能达到很好的可维护性,并且性能很好。
//MainActivity实现MainFragment开放的接口
public class MainActivity extends FragmentActivity implements FragmentListener{
@override
public void toH5Page(){ }
...其他处理代码省略
}
public class MainFragment extends Fragment{
public FragmentListener mListener;
//MainFragment开放的接口
public static interface FragmentListener{
//跳到h5页面
void toH5Page();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//对传递进来的Activity进行接口转换
if(activity instance FragmentListener){
mListener = ((FragmentListener)activity);
}
}
...其他处理代码省略
}