Fragment的粗浅理解

时间:2024-01-21 17:46:03

Fragment:

1.它是对于Activity界面实现的一种途径,相对于已经绑定的Layout,他更轻便,更灵活,更具有*度和可设计性。

2.Fragment的功能正如他的正文意思所言,他是一个片段,不同于Layout的整体界面设计,Layout是一个整体,而Fragment相当于Layout的一部分

3.Activity只能绑定一个Layout界面,但一个Activity可以添加很多个Fragment界面。

4.Fragment拥有类似于Activity的生命周期,用以配合界面显示和交互

优势:相比于Activity跟轻量级,更加地高效和方便,无需在manifests文件中注册信息

劣势:设计的界面无法像Activity一样,通过网络和包名调用,也就是说,它只能应用于本地开发

Fragment的生命周期与Activity的生命周期对比:

Fragment的粗浅理解

注:此图来自网络

Fragment的方法执行顺序:

1.在Activity执行onCreate()的时候,添加此Fragment界面,此时进入Fragment的生命周期

2.生命周期执行顺序:(如图所示,以下是对于每个函数的调用时机和函数的作用)

1.初始化阶段:

onAttach(Activity)(当Fragment关联Activity时调用)>>>onCreate()>>>onCreateView(){此方法用来设计Fragment的界面}>>>onActivityCreated(){当Activity的onCreate()方法执行后返回时调用}
2.运行阶段:

基本与Activity一致,但Fragment的生命周期受制于Activity的周期:只有当Activity的生命周期处于onResumed()时,Fragment才能正常运行

3.摧毁阶段:

onDestoryedView(){摧毁Fragment的界面视图}>>>onDestoryed()>>>onDattch(){和Activity断开关联的时候调用此方法}

Fragment的使用方法:

1.在现在的Andtoid Studio中有默认的Fragment新建方法,

2.也可以自行创立Fragment方法,完成绑定,方法基本一致,默认的新建方法已经自行添加了对应的重写方法和界面绑定。

而自定义Fragment的步骤一般如下:

1.新建一个自定义的class类,继承Frament类,在Layout文件夹下新建一个XML界面文件;

(注:继承的Fragment来自的包邮几种,v4/app,当你使用你自己定义的Fragment的时候,一定要在使用的Activity中导入对应的Fragment包,否则会报错!)

2.在自定义的class类中重写onCreateView()方法,找到新建的xml界面文件,绘制Fragment的界面,并且对于此Fragment中控件的监听也在这里设置,其他的方法根据需求重写(如果继承的是v4的Fragment,那么你还需要申明onFragmentInterActionListener接口,留待调用的Activity实现)

3.在调用的Activity中添加此Fragment界面,并实现onFragmentInterActionListener接口(此接口可以空着不必书写任何内容,而具体他是用来干什么的,也并未弄清,以后看到此处,不懂去看,懂了补充)

注:这个自定义的步骤过程,使用默认的Fragment创建,会自动添加和绑定,很是方便,即使新建的结果并不符合要求,也可以很轻松的修改。

以上步骤的具体代码体现:

package andrew.com.custompaintdemo;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;          //在此使用的是V4包的Fragment类
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; public class BlankFragment extends Fragment { private static final String ARG_PARAM1 = "param1";      //这两个参数还没有弄明白具体用途
private static final String ARG_PARAM2 = "param2"; // TODO: Rename and change types of parameters
private String mParam1;
private String mParam2; private OnFragmentInteractionListener mListener; public BlankFragment() {                      //使用自定义的Fragment必须要给出一个空的构造方法
// Required empty public constructor
} public static BlankFragment newInstance(String param1, String param2) {
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;              //这是返回Fragment对象的方法,这个方法将两个参数打包放入一个叫Argmentss属性中,
}                         //此属性在源码中解释是construction Argments的bundle对象,但未发现与Fragment有何关联 @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment               //这里用来绑定Fragment的界面和空间监听事件
return inflater.inflate(R.layout.fragment_main, container, false);
} // TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
} @Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
} @Override
public void onDetach() {
super.onDetach();
mListener = null;
} public interface OnFragmentInteractionListener {      //此接口必须在调用此Fragment的界面的Activity中实现,但可以在实现时,不做任何处理
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}

Activity界面中的代码:

package andrew.com.custompaintdemo;

import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;        //这里使用的是V7包中的AppCompatActivity,貌似V7兼容V4包的Fragment
                //但需要注意的是,AppCompatActivity与一些控件存在版本差距,导致不兼容,如出现不兼容情况,可选择直接继承Activity
public class MainActivity extends AppCompatActivity implements BlankFragment.OnFragmentInteractionListener { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (savedInstanceState ==null){  
getSupportFragmentManager()            //V7包中为getFragmentManager(),获取Fragment的管理
                       .beginTransaction()  //开始Fragment操作
                       .add(R.id.container , new BlankFragment())  //从父容器添加Fragment界面,另一种方法是replace(),此方法包含了一个界面remove()和add()方法
                       .commit();                      //提交修改
} } @Override
public void onFragmentInteraction(Uri uri) {    //这是声明后对于Fragment方法中的接口实现
                                 //可以完全不写任何内容
}
}

以上是基本的Fragment实现方法,

在基本方法的实现基础上,对于Fragment开发后出现了两种非常实用和美观的界面:SliderMenu Activity(侧滑界面),Tabbed (横向拉动切换界面)Activity。

SliderMenuActivity 源代码组成解析:

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem; public class SliderViewDemo extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slider_view_demo);        //控件组成:背景容器
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);      //控件组成:toolBar()这是一个处于顶部的横条控件
setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);    //控件组成:右下角的邮箱按钮,
fab.setOnClickListener(new View.OnClickListener() {                  //该邮箱按钮的点击监听事件
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);      //这是SliderMenu的主界面,绑定后设置一个ActionBarDrawerToggle
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(              //这里设置的navigation_drawer_open/close用于在onBackPressed中判断
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();      //可能这里有反复调用的同步逻辑,尚未研究透彻 NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);  //控件组成:左侧列表的选项视图
navigationView.setNavigationItemSelectedListener(this);                //由于本Activity实现了本方法,所以可以直接使用this
} @Override
public void onBackPressed() {                                //此函数是当界面处于左侧菜单列表时,
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);     //用于按下返回键后,回到主界面的,其中具体的函数逻辑暂时不清楚
if (drawer.isDrawerOpen(GravityCompat.START)) {                    
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) {                     //这里绑定右上角设置的menu内容
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.slider_view_demo, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {                  //这里添加对右上角setting内容的监听事件
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} @SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {              //这里添加对左侧菜单选项的监听事件
// Handle navigation view item clicks here.
int id = item.getItemId(); if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) { } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;              //经测试,这里设置为false则所有的选项监听不执行
}
}

在以上的SliderMenu Activity中使用了很多Frament的碎片化布局相互配合,共同实现了整体的界面效果,接下来解析Fragment部分的运行方式。

在XML文档中设置的Fragment界面中,共有四个界面组成部分:

1.activity_slider_view_demo(这是左侧菜单栏的Fragment)

代码分析:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
  // include是一种优化布局的方式,将app_bar_slider_view_demo这个界面在背后显示,产生层次效果
<include
layout="@layout/app_bar_slider_view_demo"
android:layout_width="match_parent"
android:layout_height="match_parent" />
   
//这是实际的左侧菜单栏的界面
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
     
     //这段代码绑定了nav_header_slider_view_demo的Fragment内容,该内容设计了左侧菜单栏的个人信息内容 
app:headerLayout="@layout/nav_header_slider_view_demo"  
//这段代码用于绑定menu中的activity_slider_view_demo_drawer界面,该界面设计了左侧菜单具体的选项内容
     app:menu="@menu/activity_slider_view_demo_drawer" />  
    (注:为结构清晰明了,在res目录下新建了menu文件夹,在此文件夹下添加的Fragment界面内容) </android.support.v4.widget.DrawerLayout>

2.app_bar_slider_view_demo

具体代码分析:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
android:fitsSystemWindows="true"
tools:context="andrew.com.custompaintdemo.SliderViewDemo"> <android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar              //这是一段系统给出的自定义控件界面,其中只有一个ToolBar,用来显示标题
android:id="@+id/toolbar"                 //此AppBarLayout仅仅占用了一个标题栏的内容
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>           <include layout="@layout/content_slider_view_demo" />    //在标题存在的情况下,使用include标签显示content_slider_view_demo界面中的内容
           //此Fragment是作为正式的显示内容,默认为空,可以由我们自己设置,使用默认的建立方法后,若想设置自己的内容样式,就是在此Fragment中设计   <android.support.design.widget.FloatingActionButton      //这是右下角的邮箱图标的控件
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>

3.content_slider_view_demo

代码分析:

<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="andrew.com.custompaintdemo.SliderViewDemo"
tools:showIn="@layout/app_bar_slider_view_demo">   //这是默认的正文显示内容,新建的时候,默认为空白
  //可以当做这里就是Activity的绑定界面,自定义一切可用控件
  //整个SliderMenu Activity只是一个框架,他提供了一个相对美观和具有良好交互体验的一个界面模板,而我们真正的设计,在这个Fragment中开始 </RelativeLayout>

4.nav_header_slider_view_demo

代码分析:

<?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="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
     //这里正式先前提到的左侧聊表的个人信息模块设计面板
  //其中包括了头像,名称,邮箱
  //若我们需要显示不同的信息内容,也可以在这里进行自定义开发
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:src="@android:drawable/sym_def_app_icon" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> <TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android.studio@android.com" /> </LinearLayout>

另外在res目录下,默认创建的menu文件中存在两个辅助文件:

1.activity_slider_view_demo_drawer(这是左侧菜单栏的选项设计)

具体代码:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single">
<item
android:id="@+id/nav_camera"                
android:icon="@drawable/ic_menu_camera"
android:title="Import" />            //选项名称:import
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />          
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</group> <item android:title="Communicate">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="Send" />
</menu>
</item> </menu>
//注:这里不再是Fragment的内容,而是资源文件

2.slider_view_demo(这里设计的是右上角的设置内容)

具体代码:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"      //这里只设计了一个setting选项
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

PS:

Tabbed Activity有时间或又需要再具体分析!