详解Android开发中Fragment的使用
作者:低调小一 发布时间:2023-05-02 20:32:25
前言
学习Java和Android将近一年的时间了,期间的成果应该就是独立完成了一个Android客户端,并且保证了其在主线版本的稳定性。期间遇到了很多坑,也跟着师兄学到了很多Android知识。但是人总是要拥抱变化,不能让自己太安逸,虽然有不舍,但是我已经证明了自己的学习能力,下一步就是开始做Rom Porting了。这里总结一下之前项目中用到最多的Fragment。
Fragment简介
Fragment可以理解成Activity中用户界面的一个行为或者一部分,它必须被嵌套在Activity中。但是一个Fragment有它自己独立的xml布局文件,并且具有良好的封装性,因此特殊情况下Fragment可以很容易用Activity来进行替换。
创建Fragment
创建一个Fragment和创建Activity类似,需要实现XML布局文件和Java Class。
XML布局文件和其他布局文件都一样,例如如下所示的布局文件(fragment_layout.xml):
<?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" >
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/testview" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button" />
</LinearLayout>
Java代码中,一般情况下可以根据需要实现Fragment以下几个生命周期方法:
1. onAttach():当Fragment依附于activity时被调用,可以在该方法中获取activity句柄,从而实现Fragment和activity之间的通信。
2. onCreate():对Fragment做初始化。
3. onCreateView():在第一次为Fragment绘制用户界面时系统会调用此方法。
4. onActivityCreated():在宿主Activity onCreate函数执行完成之后被调用,可以在这个方法里进行Fragment自己的widget实例化和业务逻辑处理。
5. onDestoryView():当Fragment开始被销毁时调用。
6. onStart():当Fragment可见时被调用。
还有许多其他用以操纵Fragment生命周期中各个阶段的回调函数,大家可自行Google学习。
Fragment生命周期
每一个Fragment都有自己的一套生命周期回调方法和处理自己的用户输入事件。对应的生命周期如下图所示:
在Activity中加入Fragment
首先,需要确保Acitivity支持Fragment,因此Activity通常需要继承自FragmentActivity。在Activity中添加Fragment通常有两种方法:静态的和动态的。
静态方法
直接在Activity的XML布局文件中加入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:baselineAligned="false"
android:orientation="horizontal" >
<fragment
android:id="@+id/first"
android:name="com.example.FristFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/second"
android:name="com.example.SecondFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<fragment>中的android:name 属性指定了布局中实例化的fragment类
当系统创建Activity布局时,它实例化了布局文件中指定的每一个Fragment,并且为它们调用onCreateView()函数,以获取每一个fragment的布局。系统直接在<fragment>元素位置插入fragment返回的view
注意:每个fragment都需要一个唯一的标识,如果重启activity,系统可用来恢复fragment(并且用来捕捉fragment的事务处理,例如移除)。为了Fragment提供ID有三种方法:
用android:id属性提供一个唯一的标识
用android:tag属性提供一个唯一的字符串
如果上述两个属性都没有,系统会使用其容器视图的ID
动态方法
使用FragmentTranscation。可以使用FragmentTranscation的API来对Activity的Fragment进行操作(例如添加,移除,或者替换Fragment)。参考代码如下:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
传入add()函数的第一个参数是Fragment被放置的ViewGroup,它由资源ID(resource ID)指定,第二个参数就是要添加的fragment。一旦通过FragmentTranscation做了更改,都应当使用commit()视变化生效。
Fragments通信
Fragments之间不应该直接进行通信,它们之间的交互应该通过宿主Activity进行。有三种Fragment和Acitivity交互的方法:
1. Activity创建带参数的Fragment。
2. Activity中保持了Fragment的对象句柄,可通过句柄直接调用该Fragment的public方法。
3. Fragment可在onAttach函数中获取定义的listener句柄。
创建带参数的Fragment
在某些特定的情况下,Fragment可能需要特定的参数来进行初始化。由于Fragment必须只有一个无参构造函数,因此可以考虑使用静态的newInstance方法来创建带参数的Fragment。示例代码如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
public class TestFragment extends Fragment {
public static TestFragment newInstance(int num, String title) {
TestFragment fragment = new TestFragment();
Bundle args = new Bundle();
args.putInt("num", num);
args.putString("title", title);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int num = getArguments().getInt("num", 0);
String title = getArguments().getString("title", "");
}
}
你可以在Activity里,简单的加载一个带参数的Fragment:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
TestFragment fragment = TestFragment.newInstance(5, "fragment title");
ft.replace(R.id.placeholder, fragment);
ft.commit();
调用Fragment的方法
因为Activity可以获取嵌入的Fragment的句柄,因此可以直接通过Fragment句柄调用该方法。
public class TestFragment extends Fragment {
public void doSomething(String param) {
// do something in fragment
}
}
在Activity中,可以直接通过Fragment的对象句柄调用该方法:
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestFragment testFragment = new TestFragment();
testFragment.doSomething("some param");
}
}
Fragment Listener
如果Fragment需要共享事件给Activity,则需要利用这个方法。Fragment中定义一个接口,并且由Activity来实现这个接口。在onAttach()方法中将实现了这个接口的Activity获得到。
在Fragment中定义接口代码如下:
import android.support.v4.app.Fragment;
public class MyListFragment extends Fragment {
// ...
// Define the listener of the interface type
// listener is the activity itself
private OnItemSelectedListener listener;
// Define the events that the fragment will use to communicate
public interface OnItemSelectedListener {
public void onRssItemSelected(String link);
}
// Store the listener (activity) that will have events fired once the fragment is attached
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
// Now we can fire the event when the user selects something in the fragment
public void onSomeClick(View v) {
listener.onRssItemSelected("some link");
}
}
在Activity中实现这个接口:
import android.support.v4.app.FragmentActivity;
public class RssfeedActivity extends FragmentActivity implements
MyListFragment.OnItemSelectedListener {
DetailFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rssfeed);
fragment = (DetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.detailFragment);
}
// Now we can define the action to take in the activity when the fragment event fires
@Override
public void onRssItemSelected(String link) {
if (fragment != null && fragment.isInLayout()) {
fragment.setText(link);
}
}
}


猜你喜欢
- 一、前言学习概述:学习四种不同类型的方法应用、方法被调用时的内存图、重载学习目标:熟练掌握方法的应用以及重载二、定义与调用1.概述定义:方法
- 觉得作者写得太好了,不得不收藏一下。对这个例子的理解://类型参数不能用基本类型,T和U其实是同一类型。//每次放新数据都成为新的top,把
- InterProcessMutex内部实现了zookeeper分布式锁的机制,所以接下来我们尝试使用这个工具来为我们的业务加上分布式锁处理的
- 前言作为Java开发者,我们每天都会创建大量的对象,但是,我们总是使用管理依赖系统(如Spring框架)来创建这些对象。其实还有其他方法可以
- 在Java中,不像Python一样直接用个input()就行的。Java控制台输入比较麻烦,下面是比较易懂的教程。首先,新建一个调用Java
- 写了一个可以扫描附近蓝牙设备的小Demo,可以查看蓝牙设备的设备名和Mac地址代码量不多,很容易看懂/** * 作者:叶应是叶 * 时间:2
- 当前的Winform分页控件中,当前导出的数据一般使用Excel来处理,Excel的文档可以用于后期的数据展示或者批量导入做准备,因此是比较
- 第一步。根据卷标,CPU序列号,生成机器码// 取得设备硬盘的卷标号
- Java BorderLayout布局管理器的两种排列java中Frame类默认的布局管理器为BorderLayout,其主要是将Frame
- IDEA 2020 源生是不支持中文的,感谢捷克工程师(可能是由国人实现)对我大天朝程序员的“照顾”,且不说这个必要性到底有多大,但从侧面体
- package com.cjonline.foundation.evisa;import java.io.BufferedReader;im
- (注意:本文基于JDK1.8)前言增删改查,修改元素,Vector提供了3个方法,包括迭代器中的一个,不过本文只分析Vector自身的两个修
- 之前有简单介绍过java多线程的使用,已经Thread类和Runnable类,为了更好地理解多线程,本文就Thread进行详细的分析。sta
- 项目中要用到以截断的方式取小数点后两位,故写了以下方法: /// <summary> /// 将小数值按指定的小数位数截断 //
- 前言:最新Servlet 3.0 * 的使用1.pom.xml添加需要使用的依赖<project xmlns="http:/
- Java中避免NullPointerException的方法总结在字符串常量上调用equals// good"string lit
- 当一个产品或者项目由大量独立模块组成时,想要从 Git 挨个下载下来导入 IDE 查看并不容易,此时可以结合使用 Git 和 Maven 的
- 一、前言在日常工作中,如果涉及到与第三方进行接口对接,有的会使用WebService的方式,这篇文章主要讲解在.NET Framework中
- 这篇文章主要介绍了Java中的3种输入方式实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可
- 智能终端上的游戏目前风头正劲,试问哪个智能手机上没有几款企鹅公司出品的游戏呢!之前从未涉猎过游戏开发,但知道游戏开发前要挑选一款合适的游戏引