博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Studio开发学习(十三)——Fragment
阅读量:3917 次
发布时间:2019-05-23

本文共 7391 字,大约阅读时间需要 24 分钟。

一、前提

Fragment作为Android最基本,最重要的基础概念之一,在开发中经常会和他打交道。Fragment有自己的生命周期,依赖于Activity,可以与Activity的相互获取(Fragment通过getActivity()获取Activity;Activity通过FragmentManger的findFragmentById()或findFragmentByTag()获取Fragment),与Activity的多对多关系

二、目标

Fragment

三、内容

1、Fragment在Activity中的基本运行

先在activity_main中添加如下布局文件,一个按钮和一个布局管理器

分别建立两个新的java文件,且其中的代码相同,这里展示一个

在xml文件中添加一个TextView

在java文件中添加

package com.example.sunny.fragment;import android.app.Fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by Sunny on 2020/4/24. */public class BFragment extends Fragment {    private TextView textView;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view=inflater.inflate(R.layout.fragmentb,container,false);        return view;    }    @Override    public void onViewCreated(View view, Bundle savedInstanceState) {        super.onViewCreated(view, savedInstanceState);        textView= (TextView) view.findViewById(R.id.tv);    }}

在此处我们可以看到java文件继承Fragment

且常用的两种方法是:

onCreateView()方法,该方法返回视图文件,相当于Activity中onCreate方法中setContentView一样

onViewCreated()方法,该方法当view创建完成之后的回调方法

说白了就是一个用于创造,一个用于运用

在onCreateView()中首先还是找到为它写的布局文件,返回视图文件

在onViewCreated()中找到其视图文件中的各类控件进行使用

 

在MainActivity中添加

package com.example.sunny.fragment;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    private AFragment aFragment;    private BFragment bFragment;    private Button button;    private TextView textView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button= (Button) findViewById(R.id.btn);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (bFragment == null) {                    bFragment = new BFragment();                }                //返回FragmentManager,用于与与此活动关联的片段进行交互;;在与这个片段管理器关联的片段上启动一系列编辑操作                getFragmentManager().beginTransaction().replace(R.id.fl, bFragment).commitAllowingStateLoss();            }        });        //实例化AFragment        //aFragment=AFragment.newInstance("hello");        aFragment=new AFragment();        //把AFragment添加到Activity中,记得调用commit        getFragmentManager().beginTransaction().add(R.id.fl,aFragment).commitAllowingStateLoss();    }

逻辑就是:首先实例化一个Fragment,将Fragment添加到Activity中,通过按钮点击跳转至另一个Fragment

getFragmentManager().beginTransaction()是固定操作,关键在于你是想要替换还是添加,都是将fragment的实例传给之前布局的LinearLayout中,最后提交,一般使用commitAllowingStateLoss()方法进行提交因为commmit()方法有时会报错

2、向Fragment传递参数

在AFragment中添加一个静态方法,在该方法中进行实例化并且返回fragment

setArguments()方法:为这个片段提供构造参数。这只能在片段被连接到它的活动之前调用;也就是说,您应该在构建片段之后立即调用它。这里提供的参数将在片段销毁和创建之间保留。

public static  AFragment newInstance(String title){        AFragment fragment=new AFragment();        Bundle bundle=new Bundle();        bundle.putString("title",title);        fragment.setArguments(bundle);        return fragment;    }

在onViewCreated()方法中添加,判断之前创建的是否存在,若存在则可赋值

if(getArguments()!=null){            textView.setText(getArguments().getString("title"));        }

最后在MainActivity中将之前实例化的语句改为

aFragment=AFragment.newInstance("hello");

3、Fragment回退栈

首先要对代码进行改动,去掉activity_main中的按钮,将它放置在AFragment的布局文件中,并且在添加一个按钮

在MainActivity中删除Button的点击事件,添加一个标记

package com.example.sunny.fragment;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    private AFragment aFragment;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);       //实例化AFragment        aFragment=AFragment.newInstance("hello");        //把AFragment添加到Activity中,记得调用commit        getFragmentManager().beginTransaction().add(R.id.fl,aFragment,"a").commitAllowingStateLoss();    }}

注意:多了的那个"a"表示一个标记,可使用它来找寻相应的片段

在AFragment的java文件中的onViewCreated()中添加

button1.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (bFragment == null) {                    bFragment = new BFragment();                }                Fragment fragment=getFragmentManager().findFragmentByTag("a");                if (fragment!=null){                    getFragmentManager().beginTransaction().hide(fragment).add(R.id.fl, bFragment).addToBackStack(null).commitAllowingStateLoss();                }else{                    getFragmentManager().beginTransaction().replace(R.id.fl, bFragment).addToBackStack(null).commitAllowingStateLoss();                }            }        });        button2.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                textView.setText("new text");            }        });

第一个按钮的作用是点击后调到下一个Fragment中,首先判断是否存在bFragment,若不存在则实例化一个,若存在,则先找是否发现标记a,若标记a的片段存在,则将它隐藏后添加新的Fragment,若不存在,则直接进行替换

addToBackStack(null)是将此事务添加到后堆栈。这意味着事务将在提交后被记住,并将在稍后弹出堆栈时反转其操作。他其中的参数是一个String name表示此回堆栈状态的可选名称,或null;一般写null;意思也就是说,添加这个方法后,你使用返回键后就会返回你的上一步操作,否则会直接回到你的首次操作,比如你有一个主页面,点击按钮后疯狂跳转,如果没有添加此方法,则点击返回键直接返回主页面,中间所有的跳转页面都不会再显示

hide()表示隐藏现有的片段。这只与那些视图已被添加到容器中的片段相关,因为这将导致视图被隐藏。这样你即使点击修改文字后,再进入BFragment后,返回看到的还是修改后的文字否则。你不管怎样更改文字内容,更换Fragment后返回看到的永远都是最初的文字,如下图

第二个按钮的作用是点击后文字改变,整个的效果

4、二者之间的通信

Fragment发送一个消息给Activity,让他去执行,利用回调接口的方法

先在AFragment的xml文件中在添加一个按钮

在AFragment的中写一个接口

private IOnMessageClick listener; public interface IOnMessageClick{        void onClick(String text);    }

在MainActivity中实现这个接口,并且重写方法

package com.example.sunny.fragment;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends AppCompatActivity implements AFragment.IOnMessageClick{    private AFragment aFragment;    private TextView textView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView= (TextView) findViewById(R.id.title);       //实例化AFragment        aFragment=AFragment.newInstance("hello");        //aFragment=new AFragment();        //把AFragment添加到Activity中,记得调用commit        getFragmentManager().beginTransaction().add(R.id.fl,aFragment,"a").commitAllowingStateLoss();    }        @Override    public void onClick(String text) {        textView.setText(text);    }}

在AFragment中,当Fragment依附于Activity时有一个方法,是onAttach(),表示当片段首次附加到其上下文时调用。

@Override    public void onAttach(Context context) {        super.onAttach(context);        try{            listener= (IOnMessageClick) context;        }catch(ClassCastException e){            e.printStackTrace();        }    }

最后在新的按钮的点击事件中添加代码

listener.onClick("succeed");

四、总结

Fragment相对来说功能强大,与Activity相辅相成,很重要的一个知识点,也比较复杂

转载地址:http://iyvrn.baihongyu.com/

你可能感兴趣的文章
骚年快答 | 技术中台与业务中台都是啥?
查看>>
骚年快答 | 微服务架构中的BFF到底是啥?
查看>>
设计模式之适配器模式
查看>>
如何利用Gitlab-CI持续部署到远程机器?
查看>>
.NET Core + K8S + Loki 玩转日志聚合
查看>>
ASP.NET Core中的分布式缓存
查看>>
在ASP.NET Core中创建自定义端点可视化图
查看>>
继续分享 5 个实用的 vs 调试技巧
查看>>
五年了,别再把务虚会开 “虚” 了
查看>>
一文看懂"async"和“await”关键词是如何简化了C#中多线程的开发过程
查看>>
每天都在支付,你真的了解信息流和资金流?
查看>>
.Net Core 自定义配置源从配置中心读取配置
查看>>
基于.NetCore3.1系列 —— 日志记录之日志配置揭秘
查看>>
设计模式之享元模式
查看>>
单例模式最佳实践
查看>>
.NET Core + Spring Cloud:服务注册与发现
查看>>
今天你内卷了吗?
查看>>
设计模式之代理模式
查看>>
在 MySQL 中使用码农很忙 IP 地址数据库
查看>>
结构型设计模式总结
查看>>