您的位置:首页 > 其它

Fragment使用详解

2017-05-01 15:24 190 查看
Fragment角色分析

Fragment是Android 3.0引入的新API。Fragment意思是片段,Activity就像是一个商店,Fragment就像是顾客,顾客在商店里才能实现顾客的身份和对应功能,商店关门(销毁),顾客身份就也不在了,顾客可以有自己的挑选商品,付费,自己离开等自己的行为。

所以梳理下来就是,Fragment必须依赖Activity生存,Fragment有自己的生命周期和操控事件,但是他的存亡依赖于父Activity。(Activity生命周期结束,他也就不存在了)

应用Fragment的意义何在

既然Fragment必须依赖Activity,为什么还要双层嵌套,这不是更浪费资源?

A Fragment is a piece of an application's user interface or behavior that can be placed
in an Activity. Interaction with fragments is done through FragmentManager, which can
be obtained via Activity.getFragmentManager() and Fragment.getFragmentManager().


官方文档有说通过FragmentManager可以更方便的替换Fragment,意思就是顾客的身份可以随时更替,不用新建Fragment所在的Activity,以往我们如果新换功能性界面是不是都需要更换Activity,那么有了Fragment,就可以动态改变当前Fragment,而他原来的Activity并么有动,Fragment的优点就是高复用性。加入我们要的界面Item过多,我们每次点击Item都会新实例化一个Activity,而相比使用Fragment来说,我们就实例化一个Activity就足够了。

Fragment实例

平时创建Activity需要继承AppCompatActivity基类,Fragmnet类似需要继承基类:



平时比较常用的是DialogFragment(对话框)、ListFragment(列表)、PreferenceFragment(选项设置)、WebViewFragment(WebView界面)。

FragmentDemo.java

public class FragmentDemo extends Fragment {

public FragmentDemo() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 加载layout布局
return inflater.inflate(R.layout.fragment_fragment_demo, container, false);
}

}


布局文件:

<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.alphathink.fragmentdemo.FragmentDemo">

<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />

</FrameLayout>


主Activity布局文件添加Fragment(用name属性添加):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.alphathink.fragmentdemo.MainActivity">

<fragment
android:name="com.alphathink.fragmentdemo.FragmentDemo"
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</RelativeLayout>


这样一个fragment布局就填好了。

运行结果:



进阶,模仿QQ下方点击换界面

简单效果:



实现也很简单,没有做相应的图片资源,所以将就一下吧:

代码,我也不贴了,有需要的下载来看就是了。地址是:

http://download.csdn.net/download/z_dinghao/9830344

注意与Activity区别较大的是:我们更换Activity是使用Intent方式来跳转,他需要调用Transaction的方式来增删操作fragment。

//从父Activity中获取FragmentManager管理器
FragmentManager fragmentManager = getSupportFragmentManager();
//调用FragmentManager的FragmentTransaction食物处理器来统一处理fragment的相关操作
FragmentTransaction transaction = fragmentManager.beginTransaction();
fragment_first = new FragmentFirst();
transaction.replace(R.id.mContent,fragment_first);
transaction.commit();


常用方法:add()、replace()、show()、attach()、remove()、hide()、detach()、commit()。

以上也只是搭建了一个简易的框架而已,各个fragment里边都是只有一句话,什么事务也没有。如果我们想在里边做些自己的事怎么做呢?其实这点就和平常的Activity中做的类似,不过还有点小区别。比如我们想在第一个fragment中设置按钮点击toast一句话这一简单操作,就要这样改第一个FragmentFirst.java

修改FragmentFirst.java

public class FragmentFirst extends Fragment {
private Button btn_test;

public FragmentFirst() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 修改前,只是加载了布局文件
//return inflater.inflate(R.layout.fragment_fragment_first, container, false);

//修改后的操作改变
View view;
view = inflater.inflate(R.layout.fragment_fragment_first, container, false);
//这里好比Activity的OnCreate()方法之后,我们在他返回View之前把自己的操作加入进去就好,注意find
ed0d
ViewById的方式
initViewId(view);
return view;
}

public void initViewId(View view){
//别忘了View参数,否则空指针了哦
btn_test = (Button) view.findViewById(R.id.btn_test);
btn_test.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//fragment中获取当前上下文使用getActivity() 即可
Toast.makeText(getActivity(),"你点击了按钮",Toast.LENGTH_SHORT).show();
}
});
}

}


布局文件就不贴了,改动的东西不多,自己试验一下即可,需要注意的也表明了,其他想要实现的功能和在Activity中类似,以此类推即可。

在调用commit()之前,可以将事务添加到fragment事务后台栈中(通过调用addToBackStatck()压栈,通过popBackStack()出栈)。这个后台栈由activity管理,并且允许用户通过按BACK键回退到前一个fragment状态。可以利用这个实现一些比如新闻界面的fragment,可以浏览历史记录。

添加Fragment的两种方式

xml布局添加

java代码中添加

其实上边我们已经分别实现过了两种方式:

方式一是在xml布局文件中通过指定fragment的name属性来指定fragment。

方式二是通过replace方法来替换GroupView实现我们的目的fragment。

Fragment的生命周期



试验fragment:

public class FragmentFirst extends Fragment {

public FragmentFirst() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("test","onCreateView");
return inflater.inflate(R.layout.fragment_fragment_first, container, false);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d("test","onAttach");
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("test","onCreate");
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("test","onActivityCreated");
}

@Override
public void onStart() {
super.onStart();
Log.d("test","onStart");
}

@Override
public void onResume() {
super.onResume();
Log.d("test","onResume");
}

@Override
public void onPause() {
super.onPause();
Log.d("test","onPause");
}

@Override
public void onStop() {
super.onStop();
Log.d("test","onStop");
}

@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("test","onDestroyView");
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d("test","onDestroy");
}

@Override
public void onDetach() {
super.onDetach();
Log.d("test","onDetach");
}
}


这里测试我们使用第二种方式,用replace方法代替ViewGroup的方式来看看日志:

启动Activity:

05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onAttach
05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onCreate
05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onCreateView
05-01 12:01:24.426 21507-21507/com.alphathink.fragmentdemo D/test: onActivityCreated
05-01 12:01:24.426 21507-21507/com.alphathink.fragmentdemo D/test: onStart
05-01 12:01:24.427 21507-21507/com.alphathink.fragmentdemo D/test: onResume


点击home键:

05-01 12:01:45.579 21507-21507/com.alphathink.fragmentdemo D/test: onPause
05-01 12:01:45.896 21507-21507/com.alphathink.fragmentdemo D/test: onStop


重新进入:

05-01 12:02:00.574 21507-21507/com.alphathink.fragmentdemo D/test: onStart
05-01 12:02:00.575 21507-21507/com.alphathink.fragmentdemo D/test: onResume


退出键:

05-01 12:04:18.315 21507-21507/com.alphathink.fragmentdemo D/test: onPause
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onStop
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDestroyView
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDestroy
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDetach


onAttach():fragment被依附到Activity上调用,只被调用一次。

onCreate():fragment创建调用

onCreateView():创建、绘制该fragment调用

onActivityCreated():fragment依附的Activity启动后调用

onStart():fragment启动调用

onResume():fragment显示时调用

onPause():暂停fragment调用

onStop():停止fragment调用

onDestroyView():销毁fragment所包含的View时视图调用

onDestroy():销毁fragment调用,只调用一次

onDetach():fragment从Activity中解绑时调用,只会调用一次

结合log我们可以体会下fragment的生命周期,比activity稍微多了几个方法。

Fragment与Activity的交互

Activity向Fragment传送数据:利用Bundle,调用fragment的Fragment.setArguments(Bundle bundle)方法传递

Fragment向Activity传递数据,需要在Fragment定义回调接口,Activity实现Fragment的回调接口CallBacks即可。

Activity还可引用无界面的Fragment,要添加没有界面的fragment ,可使用add(Fragment, String)(为fragment提供一个唯一的标识string,而不是视图(view)ID)。这样添加了fragment,但是,因为还没有关联到activity布局中的视图(view) ,收不到onCreateView()的调用。所以不需要实现这个方法。  对于无界面fragment,字符串标签是唯一识别它的方法。如果之后想从activity中取到fragment,需要使用findFragmentByTag()。

在Fragment中可以通过getActivity得到当前绑定的Activity的实例。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fragment