前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android入门教程 | Fragment (加载方法与通信)

Android入门教程 | Fragment (加载方法与通信)

原创
作者头像
Android_anzi
修改2021-10-25 10:43:52
6090
修改2021-10-25 10:43:52
举报

Fragment 加载方法

加载方法有两种

  • 在xml文件中注册
  • 在Java代码中加载

xml中注册

例如在 fragment_demo.xml 中定义

代码语言:javascript
复制
<?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" >
    <fragment
        android:id="@+id/main_fragment_up"
        android:name="com.rust.fragment.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/main_fragment_bottom"
        android:name="com.rust.fragment.SecondFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

com.rust.fragment.SecondFragment 就是 Fragment 子类 在SecondFragment.java里复写onCreateView方法,并返回定义好的view

activity 中直接加载即可

代码语言:javascript
复制
setContentView(R.layout.fragment_demo);

Java代码中加载

①准备好Fragment xml布局文件 ②新建一个类,继承自 Fragment;在这个类中找到 Fragment 布局文件 ③在 Activity 中使用 FragmentManager 来操作 Fragment ④别忘了commit

先自定义一个布局文件 fragment_first.xml

代码语言:javascript
复制
<?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"
    android:background="#0011ff" >
<!-- <Button
    android:id="@+id/btn_fragment1_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/btn_fragment1"
    android:textSize="16sp"
       />
<EditText
    /> -->
</LinearLayout>

新建一个类 FirstFragment.java,继承自 Fragment。复写 onCreateView 方法。在onCreateView方法中,可以操作 Fragment 上的控件。

代码语言:javascript
复制
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_first, container,false);
//    fragment_first是自定义好的布局
//    如果此Fragment上放了控件,比如Button,Edittext等。可以在这里定义动作
  btn_fragment1_send = (Button) rootView.findViewById(R.id.btn_fragment1_1);
//...
        return rootView;
    }

准备一个位置给 Fragment,比如在 activity_main.xml 中用 Framelayout 来占位。

代码语言:javascript
复制
    <FrameLayout
        android:id="@+id/layout_container1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" >
    </FrameLayout>

MainActivity.java 里,先获得 FragmentManager,得到FragmentTransaction。Fragment 的添加删除等操作由 FragmentTransaction 来完成。

代码语言:javascript
复制
f1 = new FirstFragment();    //    获取实例
f2 = new SecondFragment();    //
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.layout_container1,f1);    //    添加
fragmentTransaction.replace(R.id.layout_container1,f1);    //    替换
// 或者也可以写成
fragmentTransaction.replace(R.id.layout_container1,new FirstFragment());
//              fragmentTransaction.addToBackStack(null);   //添加到返回栈,这样按返回键的时候能返回已添加的fragment
fragmentTransaction.commit();    //别忘了commit
//    移除操作 getFragmentManager().beginTransaction().remove(f1).commit();

相比与 xml 中注册,代码加载更为灵活一些。个人较为喜欢动态加载。

Fragment 与 Activity 之间的配合

Activity 先执行onResume 然后当前 Fragment 执行onResume 当前Fragment 被 replace 掉,再次 replace 回来时,有些状态并未重新初始化。 执行 replace 时会把 Fragment 的声明周期再跑一遍。稳妥的做法是,在onCreateView中初始化必要的变量。比如重置一些状态值。在多个 Fragment中切换时需要特别注意。

Fragment 间的通信

在 Fragment 的 java 文件中,可以使用 getActivity() 来获得调用它的 activity,然后再找到另一个 Fragment,进行通信

代码语言:javascript
复制
getActivity().getFragmentManager().findFragmentById(R.id.fragment_list);

但这样做耦合度太高,不方便后续的修改操作

Fragment 与其附着的 Activity 之间的通信,都应该由 Activity 来完成;不能是多个 Fragment 之间直接通信

Fragment与其附着的Activity之间通信方式:
  • 在发起事件的Fragment中定义一个接口,接口中声明你的方法
  • 在onAttach方法中要求Activity实现该接口
  • 在Activity中实现该方法

例如一个 activity 中布置了 2 个 Fragment,它们之间的通信要依靠 activity 来完成

代码:ListStoreActivity.java NewItemFragment.java ListStoreFragment.java

布局文件为:liststore.xml new_item_fragment.xml

准备布局文件

liststore.xml 用 LinearLayout 中放置了 2 个 fragment,分别指向 2 个Fragment 文件 new_item_fragment.xml 中并排放置一个 EditText 和一个按钮

ListStoreFragment.java 使用前面定义的界面

代码语言:javascript
复制
public class ListStoreFragment extends ListFragment{
/// 继承自ListFragment,已经封装好了listview
/// 不需要自己写ListView了
}

NewItemFragment.java

代码语言:javascript
复制
/**
 * 声明一个接口,定义向activity传递的方法
 * 绑定的activity必须实现这个方法
 */
    public interface OnNewItemAddedListener {
        public void newItemAdded(String content);
    }
    private OnNewItemAddedListener onNewItemAddedListener;
    private Button btnAddItem;
    /*复写onAttach方法*/
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            onNewItemAddedListener = (OnNewItemAddedListener) activity;
        } catch (ClassCastException e){
            throw new ClassCastException(activity.toString() + "must implement OnNewItemAddedListener");
        }
    }

ListStoreActivity.java 加载主视图liststore.xml;

两个 Fragment 通过ListStoreActivity来通信

在 onCreate 方法中获取 ListStoreFragment 的实例;并且复写 newItemAdded 方法,在里面加上业务逻辑

代码语言:javascript
复制
public class ListStoreActivity extends Activity implements OnNewItemAddedListener{

    private ArrayList<String> data;
    private ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.liststore);
        data = new ArrayList<String>();
        // 把data装入adapter中
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
        // ListFragment并不需要再定义一个listview 
        ListStoreFragment listStoreFragment = (ListStoreFragment) getFragmentManager().findFragmentById(R.id.fragment_listview);
        listStoreFragment.setListAdapter(adapter);
    }

    @Override
    public void newItemAdded(String content) {
        //  复写接口中的方法,业务代码在这里实现
        if(!content.equals("")) {
            data.add(content);
            adapter.notifyDataSetChanged();
        }
    }
}

这样做的缺点是耦合度很高

Fragment跟Activity的几种通信方式

  • Activity把自己的handler交给Fragment
  • 广播
  • EventBus
  • 定义接口

除了上面提到的几种方法,也可以用 Activity 和 Fragment 共用 ViewModel的方式实现通信。

Android零基础入门教程视频参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Fragment 加载方法
  • Fragment 间的通信
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档