本篇主要复习Fragment的清单如下:
-
Fragment的生命周期
-
Fragment加载的两种方式
-
Fragment之DialogFragment使用
-
Fragment通信
-
使用Fragment时的注意事项
一.Fragment的生命周期
a. 官方生命周期图
b.Fragment生命周期方法调用场景
方法 | 解释 |
---|---|
onAttach() | Fragment和Activity建立联系时调用(获取Activity传递的值 ) |
onCreateView() | 为Fragment 创建View(加载布局)时调用 |
onActivityCreated() |
Activity 的onCreate() 方法执行完毕后调用 |
onDestoryView() |
Fragment 布局被移除时调用 |
onDetach() |
Fargment 和Activity 解除关联时调用 |
c.Fragment和Activity生命周期对比图
1.创建流程:先执行
Activity
的生命周期回调,在执行Fragment
方法
2.销毁流程:先执行Fragment
的生命周期,在执行Acstivity
的方法
二.Fragment加载方式
a.静态加载
Fragment的静态添加 :
//BlankFragment.java
public class BlankFragment extends Fragment {
public BlankFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 1. 加载布局,第三个参数必须为`false`,否则会加载两次布局并且抛出异常!!
return inflater.inflate(R.layout.fragment_blank, container, false);
}
}
//fragment的布局
<FrameLayout 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.example.a6005001819.androiddeveloper.Fragment.BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
在Activity的布局文件中添加:
//如一般Activity代码-直接省略
如果Fragment
使用的是support-v4
中的, Activity需要继承自FragmentActivity
Activity的布局
//用fragment标签加载fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.a6005001819.androiddeveloper.MainActivity">
<fragment
android:id="@+id/example_fragment"
android:name="com.example.a6005001819.androiddeveloper.Fragment.BlankFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
1 如果
Fragment
属于android.support.v4.app.Fragment
包,所用Activity
必须继承FragmentActivity
2 如果Fragment
属于android.app.Fragment
,直接使用Activity即可
b 动态加载
- Fragment代码不变
- Activity中进行动态添加
public class MainJavaActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_java);
//1. 获取FragmentManager
FragmentManager fragmentManager = getFragmentManager();
//2. 获取FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//3. 创建Fragment
BlankFragment blankFragment = new BlankFragment();
//4. 将Fragment替换到Activity的布局中(Framelayout)
fragmentTransaction.add(R.id.main_java_activity_container, blankFragment);
fragmentTransaction.commit();
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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.example.a6005001819.androiddeveloper.MainJavaActivity">
<FrameLayout
android:id="@+id/main_java_activity_container"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</android.support.constraint.ConstraintLayout>
重复添加
问题:
Fragment
的动态添加是在onCreate()
中,当手机横竖屏切换,会导致多次调用onCreate()
最终导致创建多个Fragment
解决办法:在onCreate()
检查参数savedInstanceState
来确定是第一次运行还是恢复后运行
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_java);
if(savedInstanceState == null){
//1. 获取FragmentManager(support-v4中用`getSupportFragmentManager`)
FragmentManager fragmentManager = getFragmentManager();
//2. 获取FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//3. 创建Fragment
BlankFragment blankFragment = new BlankFragment();
//4. 将Fragment替换到Activity的布局中(Framelayout)
fragmentTransaction.add(R.id.main_java_activity_container, blankFragment);
fragmentTransaction.commit();
Log.i("feather", "创建新的Fragment");
}
}
三 DialogFragment 使用
a DialogFragment的作用与优缺点
DialogFragment在Android 3.0提出,用于替代Dialog
优点:旋转屏幕也能保留对话框状态
自定义对话框样式: 继承DialogFragment并重写onCreateView(),该方法返回对话框UI
//自定义DialogFragment
public class CustomDialogFragment extends DialogFragment{
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
//1. 消除标题
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
//2. 自定义样式
View root = inflater.inflate(R.layout.fragment_blank, container);
return root;
}
}
//使用DialogFragment
CustomDialogFragment dialogFragment = new CustomDialogFragment();
dialogFragment.show(getFragmentManager(), "dialog");
四 Fragment的通信
a EventBus是解决Fragment通信的终极解决方案
1.Fragment通信涉及:Fragment向Activity传递数据、Activity向Fragment传递数据、Fragment之间床底数据
- EventBus: 一个Android事件发布/订阅轻量级框架—能够便捷、高效解决Fragment所有通信问题
b Fragment和Activity
- Fragment调用Activity中的方法
1.getActivity()或者onAttach()中Context转为Activity(
不推荐使用getActivity获取,容易空指针
)
2.用该Activity对象,调用Activity的对象方法。
- Activity调用Fragment中的方法
1.Activity中直接用该Fragment对象去调用方法。
2.用过接口回调
- Activity向Fragment传递数据
1.通过构造函数传递数据(不推荐)
2.通过参数传递数据,在Fragment中onAttach()中getArguments()
3.在Activity中获取Fragment对象,直接调用Fragment的方法,通过参数传递数据
- Fragment之间的通信
1.需要借助Activity进行数据通信
2.Activity中通过FragmentManager的findFragmentById去获取Fragment
五 使用Fragment时的注意事项
- Fragment的常见问题,以及如何处理?
1.getActivity()空指针:常见于进行异步操作的时候,此时如果Fragment已经onDetach(),就会遇到。解决办法:在Fragment里面使用一个全局变量mActivity,可能会导致内存泄露。但是比崩溃更好。
2.视图重叠:主要是因为Fragment的onCreate()中没有判断saveInstanceSate == null,导致重复加载了同一个Fragment
- Fragment的切换方式有多少种?
1.add()、replace()、remove(): 会将Fragment进行移除(就是回收了实例),每次都会新建一个实例。
2.hide()、show()
3.detach()、attach()
- add和replace的区别
1.replace会将栈中的fragment全部remove,再add进行添加。
2.add是在原有基础上进行添加。
- Fragment中onCreateView()
1.内部加载布局的inflate()的第三个参数必须是false,否则会导致重复添加,抛出异常
- Fragment需要传入参数该怎么做?
1.应该通过setArguments(Bundle bundle)方法添加
2.之后通过onAttach()中的getArguments()获得传进来的参数。
3.不建议通过给Fragment添加带参数的构造函数来传参数,这样内存紧张时被系统杀掉会导致无法恢复数据
- Fragment中获取Activity对象
1.不应该!使用getActivity()获取
2.应该在onAttach()中将Context对象强转为Activity对象
- 不能在onSaveInstanceState()后调用commit()
1.onSaveInstanceState()在onPause()和onStop()之间调用。
2.onRestoreInstanceState()在onStart()和onResume()之间调用。
避免异常方法:
3.不要把Fragment事务放在异步线程的回调中,比如不要把Fragment事务放在AsyncTask的onPostExecute()—onPostExecute()可能会在onSaveInstanceState()之后执行。
4.无可奈何时使用commitAllowingStateLoss()-一般不推荐。
希望这篇文章对你有帮助~
推荐大神最全面的Fragment解析
YoKey之Fragment全解析系列
网友评论