Android基础总结2 ---- Fragment与Activity

来源:互联网 发布:xmind mac怎么安装 编辑:程序博客网 时间:2024/05/21 03:17

Android基础总结2 ---- Fragment与Activity
在Android的基础中,除了各种控件的使用之外,Fragment和Activity也是很重要的知识点。本博文参考了慕课网的Android的教学资源,学习了一段时间,很有一种想和大家分享的冲动

  • 1.Fragment作为Activity界面的一部分组成出现
  • 2.可以在一个Activity中同时出现多个Fragment,并且,一个Fragment亦可在多个Activity中使用。
  • 3.在Activity运行过程中,可以添加、移除或者替换Fragment(add()、remove()、replace()) 
  • 4.Fragment可以响应自己的输入事件,并且有自己的生命周期,当然,它们的生命周期直接被其所属的宿主activity的生命周期影响。
先看看Fragment 的生命周期吧!看下图,这里不多做解释。

下面是Fragment的生命周期的验证程序:注意看注释就明白了

package com.example.fragmentdome;import android.app.Activity;import android.app.Fragment;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class MyFragment3 extends Fragment {private TextView tv;// 启动Fragment——>屏幕锁屏——>屏幕解锁——>//切换到其他的Fragment——>回到桌面——>回到应用——>退出Fragment/** * 每次创建都会绘制Fragment的View组件时回调该方法 */@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// TODO Auto-generated method stubView view = inflater.inflate(R.layout.fragment2, container, false);TextView tv = (TextView) view.findViewById(R.id.text);tv.setText("第一个Fragment");Log.i("Main", "Fragment1---onCreateView()");return view;}/** * 当Fragment被添加到Activity时候会回调这个方法,并且只调用一次 */@Overridepublic void onAttach(Activity activity) {// TODO Auto-generated method stubsuper.onAttach(activity);Log.i("Main", "Fragment1---onAttach()");}/** * 创建Fragment时会回调,只会调用一次 */@Overridepublic void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);Log.i("Main", "Fragment1---onCreate()");}/** * 当Fragment所在的Activty启动完成后调用 */@Overridepublic void onActivityCreated(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onActivityCreated(savedInstanceState);Log.i("Main", "Fragment1---onActivityCreated()");}/** * 启动Fragment *  */@Overridepublic void onStart() {// TODO Auto-generated method stubsuper.onStart();Log.i("Main", "Fragment1---onStart()");}/** * 恢复Fragment时会被回调,调用onStart()方法后面一定会调用onResume()方法 */@Overridepublic void onResume() {// TODO Auto-generated method stubsuper.onResume();Log.i("Main", "Fragment1---onResume()");}/** * 暂停Fragment */@Overridepublic void onPause() {// TODO Auto-generated method stubsuper.onPause();Log.i("Main", "Fragment1---onPause()");}/** * 停止Fragment */@Overridepublic void onStop() {// TODO Auto-generated method stubsuper.onStop();Log.i("Main", "Fragment1---onStop()");}/** * 销毁Fragment所包含的View组件时 */@Overridepublic void onDestroyView() {// TODO Auto-generated method stubsuper.onDestroyView();Log.i("Main", "Fragment1---onDestroyView()");}/** * 销毁Fragment时会被回调 */@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();Log.i("Main", "Fragment1---onDestroy()");}/** * Fragment从Activity中删除时会回调该方法,并且这个方法只会调用一次 */@Overridepublic void onDetach() {// TODO Auto-generated method stubsuper.onDetach();Log.i("Main", "Fragment1---onDetach()");}}


接下来看看Fragment的实现吧:

1 为Frangment添加用户界面:

  fragment一般作为activity的用户界面的一部分,把它自己的layout嵌入到activitylayout中。一个要fragment提供layout,你必须实现onCreateView()回调方法,然后在这个方法中返回一个View对象,这个对象是fragmentlayout的根。看下面的代码:

public class MyFragment extends Fragment{private String aaa;public String getAaa() {return aaa;}public void setAaa(String aaa) {this.aaa = aaa;}/* * setContentView和inflate的区别 * setContentView()一旦调用, layout就会立刻显示UI * 而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。 * 一般在activity中通过setContentView()将界面显示出来,但是如果在非activity中如何对控件布局设置操作了, * 这就需要LayoutInflater动态加载。 */@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {//layout布局文件转换成View对象/** * inflate就相当于将一个xml中定义的布局找出来. * inflater.inflate(resource, root, attachToRoot); * resource:Fragment需要加载的布局文件 * root:加载layout的父ViewGroup * attactToRoot:false,不返回父ViewGroup */View view = inflater.inflate(R.layout.fragment, container, false);TextView text=(TextView) view.findViewById(R.id.text);Button button=(Button) view.findViewById(R.id.button);text.setText("静态加载Fragment");button.setText("获取内容");button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString value = getAaa();Toast.makeText(getActivity(), "value="+value, Toast.LENGTH_SHORT).show();<span style="white-space:pre"></span>}});return view;}}

上面的代码中还要注意注释部分:
/* * setContentView和inflate的区别 * setContentView()一旦调用, layout就会立刻显示UI * 而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来 * 一般在activity中通过setContentView()将界面显示出来,但是如果在非activity中如何对控件布局设置操作了, * 这就需要LayoutInflater动态加载。 */
<pre name="code" class="java" style="font-size: 18px;">//layout布局文件转换成View对象/** * inflate就相当于将一个xml中定义的布局找出来. * inflater.inflate(resource, root, attachToRoot); * resource:Fragment需要加载的布局文件 * root:加载layout的父ViewGroup * attactToRoot:false,不返回父ViewGroup */

注:如果你的fragment是从ListFragment中派生的,就不需要实现onCreateView()方法了,因为默认的实现已经为你返回了ListView控件对象。    要从onCreateView()方法中返回layout对象,你可以从layoutxml中生成layout对象。为了帮助你这样做,onCreateView()提供了一个LayoutInflater对象。

 另外,onCreateView()参数中的container是存放fragmentlayoutViewGroup对象savedInstanceState参数是一个Bundle,跟activityonCreate()Bundle差不多,用于状态恢复。此处的Bundle中存放的数据与onCreate()中存放的数据还是不同的。

Inflate()方法有三个参数:

  • 1 layout的资源ID。
  • 2 存放fragment的layout的ViewGroup。
  • 3 布尔型数据表示是否在创建fragment的layout期间,把layout附加到container上了

 2 把Frangment添加到Activity:

在Activity中加载Frangment的方式有2种,一种是静态加载(通过XML静态配置),一种是动态加载(通过程序动态创建)。

如方法一:在activity的layoutxml文件中声明fragment (静态配置)

看程序:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <EditText        android:id="@+id/editText"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <Button        android:id="@+id/send"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="发送" />    <!-- 静态加载传值 -->    <fragment         android:id="@+id/frag"        android:name="com.example.fragmentdome.MyFragment"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        /></LinearLayout>

当系统创建layout时,它实例化fragment,然后调用onCreateView()方法,以获取fragment的layout。系统把fragment返回的view对象插入到<fragment>元素的位置,直接代替<fragment>元素。每个fragment都需要提供一个ID,系统在activity重新创建时用它来恢复fragment们,你也可以用它来操作fragment进行其它的事物,比如删除它。


有三种方法给fragment提供ID:

  • 1 为android:id属性赋一个数字。
  • 2 为android:tag属性赋一个字符串。
  • 3如果你没有使用上述任何一种方法,系统将使用fragment的容器的ID

方法二:在代码中添加fragment到一个ViewGroup(动态加载)

  <span style="white-space:pre"></span>MyFragment2 fragment2=new MyFragment2();            //从 FragmentManager 获得一个FragmentTransaction的实例 :            FragmentManager fragmentManager = getFragmentManager();            FragmentTransaction beginTransaction = fragmentManager.beginTransaction();            //通过Fragment的ID来加载            beginTransaction.add(R.id.frame, fragment2);            /*             * 在调用commint()之前,你可以用addToBackStack()把事务添加到一个后退栈中,             * 这个后退栈属于所在的activity。有了它,就可以在用户按下返回键时,返回到fragment们执行事务之前的状态。             */            beginTransaction.addToBackStack(null);            beginTransaction.commit();
/* * 解释:调用addToBackStack(),fragment就被放入后退栈中,于是当用户按下返回键时,事务发生回溯,原先的fragment又回来了。 * 如果你向事务添加了多个动作,比如多次调用了add(),remove()等之后又调用了addToBackStack()方法, * 那么所有的在commit()之前调用的方法都被作为一个事务。当用户按返回键时,所有的动作都被反向执行(事务回溯)。 * 事务中动作的执行顺序可随意,但要注意以下两点: * 1. 你必须最后调用commit()。 * 2. 如果你添加了多个fragment,那么它们的显示顺序跟添加顺序一至(后显示的覆盖前面的)。 */

    为了完成fragment的事务(比如添加,删除,替换等),你必须使用FragmentTransaction的方法。你可以从activity获取到FragmentTransaction,如上面的

FragmentManager fragmentManagergetFragmentManager()
FragmentTransaction fragmentTransactionfragmentManager.beginTransaction();

  然后你可以用add()方法添加一个fragment;

  最后必须调用方法commit()提交这些改变。


3 与其他Fragment的通讯


这个其实很简单,依靠Frangment的事务处理机制发送数据。首先定义一个Bundle,将要出入的数据设置好。然后利用fragment.setArguments(bundle);发送数据包,利用管理者模式,管理事务的模式,通过Fragment的Tag方式来加载到指定的Frangment.最后不要忘了提交事务。看程序:

package com.example.fragmentdome;import com.example.fragmentdome.MyFragment5.MyListener;import android.app.Activity;import android.app.Fragment;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity4 extends Activity implements MyListener {private EditText editext;private Button send;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.main4);editext = (EditText) findViewById(R.id.editText);send = (Button) findViewById(R.id.send);send.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString text = editext.getText().toString();MyFragment5 fragment5 = new MyFragment5();Bundle bundle = new Bundle();bundle.putString("name", text);//发送数据包fragment5.setArguments(bundle);//管理者模式,管理事务的模式FragmentManager fragmentManager = getFragmentManager();FragmentTransaction beginTransaction = fragmentManager.beginTransaction();//通过Fragment的Tag方式来加载beginTransaction.add(R.id.layout, fragment5, "fragment5");beginTransaction.commit();Toast.makeText(MainActivity4.this, "向Fragment发送数据" + text,Toast.LENGTH_SHORT).show();}});FragmentManager fragmentManager = getFragmentManager();Fragment findFragmentById = fragmentManager.findFragmentById(R.id.frag);        MyFragment frag=(MyFragment) findFragmentById;        frag.setAaa("fragment静态传值");}@Overridepublic void thank(String code) {// TODO Auto-generated method stubToast.makeText(MainActivity4.this, "已成功接收到" + code + ",客气了!",Toast.LENGTH_SHORT).show();}}








0 0