浅谈fragment

Fragment

要讨论fragment首先我们得知道什么是fragment,fragment有什么用,我们为什么要使用fragment,在安卓中,fragment有着相当重要的作用,那么,我们今天就来浅谈一下fragment

Fragment是什么

相信大家对QQ肯定不陌生,那么我们都知道,QQ上有以下几个按钮
这里写图片描述
对应的分别是联系人,空间,群组和消息,而当我们点击其中一个时,就会切换到对应的页面(当然,空间标记除外),其实这其中就使用了fragment,fragment是一个碎片,只能依附在activity页面才能显示,就像我们刚刚所说,切换的每一个页面就是一个fragment,fragment的诞生是最初是为了适应平板,fragment的诞生解决了屏幕适配问题,因为fragment是一个局部的碎片,在局部刷新方面也有着独特的优势,说了这么多,那么,到底什么是fragment呢?

Fragment也可以叫为“片段”,它可以表示Activity中的行为或用户界面部分。我们可以在一个Activity中用多个Fragment组合来构建多窗格的UI,以及在多个Activity中重复使用某个Fragment。它有自己的生命周期,能接受自己的输入,并且可以在 Activity 运行时添加或删除Fragment(有点像在不同 Activity 中重复使用的“子 Activity”)。

简单来说,Fragment其实可以理解为一个具有自己生命周期的控件,只不过这个控件又有点特殊,它有自己的处理输入事件的能力,有自己的生命周期,又必须依赖于Activity,能互相通信和托管。

Fragment的静态加载

知道了什么是fragment,那么我们当然得知道fragment的两种加载方式
首先,我们来看一看fragment的静态加载,fragment的静态加载,说白了就是直接将fragment放到activity中使用,相比较起来较为容易使用,那么,我们来创建一个fragment碎片(以Android Studio为例):
这里写图片描述
我创了一个fragment的包,为了看的更清楚,按照我选择的步骤就可以创出一个简单的fragment
这里写图片描述
这里要注意
这里写图片描述
这两个选项本来是默认选上的,我们得把它去掉,不然后面的代码很可能会报错,创好的fragment其实也相当于一个activity,有布局页面和java代码页面,在这两个页面中可以进行我们自己的一些操作,这里我们主要来说说fragment的静态加载的方法,其实很简单,我们只需要在一个布局中直接加入fragment就行:

<fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.asus.mytest2.fragment.ExampleFragment"
        android:id="@+id/fragment_example"/>

这里我们说下fragment标签的一个重要属性

name:这个属性用来选择你所需要放置在activity中的fragment碎片

这里我们说一下,id必须得写

fragment的静态加载基本上就是这样,这样我们在碎片上写的内容就可以在activity被运行时显示出来

Fragment的动态加载

有静态加载就肯定会有动态加载,比起静态加载来,fragment的动态加载会有更多需要注意的地方
同样,我们先创建一个fragment的碎片,这是创好的fragment中activity的代码:

package com.example.asus.mytest2.fragment;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.asus.mytest2.R;

/**
 * A simple {@link Fragment} subclass.
 */
public class ExampleFragment extends Fragment {


    public ExampleFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_example, container, false);
    }

}

当然,我们的重点是看上面的包,是不是发现了一个v4包

import android.support.v4.app.Fragment;

这是我们创建fragment默认加载的包,而fragment的动态加载需要的是app包,这里我们得去掉这个包重新导一个包

import android.app.Fragment;

这是新导入的包,对于动态加载,我们则需要新引入一个标签FrameLayout

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fragment"
        android:layout_above="@id/ll_fragment"
        ></FrameLayout>

使用这个标签来进行fragment的动态加载,在这里我们先说说关于动态加载几个包

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性

这里我们说下动态加载的两个属性

获取FragmentManage的方式有:android.app.Fragment:getFragmentManager() ;

FragmentTransaction transaction = fm.benginTransatcion()用来开启一个事务

这里为了方便大家理解,我们来写个例子,我们先创建三个fragment碎片HelloFragment,ListFragment,WxFragment,在activity中加入FrameLayout标签:

<?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"
    tools:context="com.example.asus.mytest2.FragmentActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true"
        android:id="@+id/ll_fragment">

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="联系人"
            android:id="@+id/btn1_fragment"/>
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="动态"
            android:id="@+id/btn2_fragment"/>
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="微信"
            android:id="@+id/btn3_fragment"/>

    </LinearLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fragment"
        android:layout_above="@id/ll_fragment"
        ></FrameLayout>

</RelativeLayout>

这里,我们就要用到刚刚所说的FragmentManager和FragmentTransaction,附上activity代码:

public class FragmentActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn1, btn2, btn3;
    private FragmentManager fragmentManager;
    private FragmentTransaction fragmentTransaction;
    private HelloFragment helloFragment;
    private ListFragment listFragment;
    private WxFragment wxFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        btn1 = (Button) findViewById(R.id.btn1_fragment);
        btn2 = (Button) findViewById(R.id.btn2_fragment);
        btn3 = (Button) findViewById(R.id.btn3_fragment);

        fragmentManager = getFragmentManager();

        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        btn3.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.btn1_fragment:
                if (helloFragment == null) {
                    helloFragment = new HelloFragment();
                }
                fragmentTransaction.replace(R.id.fragment, helloFragment);
                break;
            case R.id.btn2_fragment:
                if (listFragment == null) {
                    listFragment = new ListFragment();
                }
                fragmentTransaction.replace(R.id.fragment, listFragment);
                break;
            case R.id.btn3_fragment:
                if (wxFragment == null) {
                    wxFragment = new WxFragment();
                }
                fragmentTransaction.replace(R.id.fragment, wxFragment);
                break;
            default:
                break;
        }
        fragmentTransaction.commit();
    }
}

这里要注意的是要用到的包是app包,导错包的话就会报错的,附上结果截图一张
这里写图片描述
我在这边因为设置了按钮的单机事件,所以点击不同的按钮就会跳转不同的fragment中

ViewPager+Fragment实现页卡滑动

下面,我们来做一个关于页卡滑动的实例,这里因为ViewPager是属于四包,所以我们需要的fragment就不用修改成app包了,同样是创建三个fragment碎片,这里我就不放fragment的代码了,直接上布局代码

<?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:orientation="vertical"
    tools:context="com.example.asus.mytest2.ViewPagerActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true"
        android:id="@+id/ll_viewpager">

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="大笨妞"
            android:id="@+id/btn1_viewpager"/>
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="大傻妞"
            android:id="@+id/btn2_viewpager"/>
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="大蠢妞"
            android:id="@+id/btn3_viewpager"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_above="@id/ll_viewpager"
        android:id="@+id/ll">

        <View
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_weight="1"
            android:background="#000000"
            android:id="@+id/view1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_weight="1"
            android:id="@+id/view2"/>
        <View
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_weight="1"
            android:id="@+id/view3"/>

    </LinearLayout>

    <android.support.v4.view.ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewPager"
        android:layout_above="@id/ll">

    </android.support.v4.view.ViewPager>

</RelativeLayout>

这里说一下,关于ViewPager的使用我们这需要用到适配器,具体可以去看看我写的适配器博客,这里我就直接发出代码

public class ViewAdapter extends FragmentPagerAdapter {

    private List<Fragment>fragmentList;

    public ViewAdapter(FragmentManager fm,List<Fragment>fragmentList) {
        super(fm);
        this.fragmentList=fragmentList;
    }

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }
}

下面就是我们的重点activity代码了

public class ViewPagerActivity extends AppCompatActivity implements View.OnClickListener {

    private ViewPager viewPager;
    private BenFragment benFragment;
    private ShaFragment shaFragment;
    private ChunFragment chunFragment;
    private Button btn1, btn2, btn3;
    private View view1, view2, view3;

    private List<Fragment> fragmentList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        view1 = findViewById(R.id.view1);
        view2 = findViewById(R.id.view2);
        view3 = findViewById(R.id.view3);
        btn1 = (Button) findViewById(R.id.btn1_viewpager);
        btn2 = (Button) findViewById(R.id.btn2_viewpager);
        btn3 = (Button) findViewById(R.id.btn3_viewpager);

        view1.setBackgroundColor(Color.BLACK);

        benFragment = new BenFragment();
        shaFragment = new ShaFragment();
        chunFragment = new ChunFragment();

        fragmentList.add(benFragment);
        fragmentList.add(shaFragment);
        fragmentList.add(chunFragment);

        ViewAdapter adapter = new ViewAdapter(getSupportFragmentManager(), fragmentList);
        viewPager.setAdapter(adapter);

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                view1.setBackgroundColor(Color.WHITE);
                view2.setBackgroundColor(Color.WHITE);
                view3.setBackgroundColor(Color.WHITE);
                switch (position) {
                    case 0:
                        view1.setBackgroundColor(Color.BLACK);
                        break;
                    case 1:
                        view2.setBackgroundColor(Color.BLACK);
                        break;
                    case 2:
                        view3.setBackgroundColor(Color.BLACK);
                        break;
                    default:
                        break;
                }

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        btn3.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1_viewpager:
                viewPager.setCurrentItem(0);
                break;
            case R.id.btn2_viewpager:
                viewPager.setCurrentItem(1);
                break;
            case R.id.btn3_viewpager:
                viewPager.setCurrentItem(2);
                break;
            default:
                break;
        }
    }
}

public void onPageSelected:用来获取选中页面时的光标变色

viewPager.setCurrentItem(0):用来实现点击跳转到对应的fragment页面

附上结果截图一张
这里写图片描述

Fragment的生命周期

这里先放上一张关于fragment生命周期的图片
这里写图片描述
可以看到Fragment比Activity多了几个额外的生命周期回调方法:

onAttach(Activity)

当Fragment与Activity发生关联时调用。

onCreateView(LayoutInflater, ViewGroup,Bundle)

创建该Fragment的视图

onActivityCreated(Bundle)

当Activity的onCreate方法返回时调用

onDestoryView()

与onCreateView想对应,当该Fragment的视图被移除时调用

onDetach()

与onAttach相对应,当Fragment与Activity关联被取消时调用
其实这张图已经说明了activity的生命周期,但是在这里需要的注意的是,

(1)onCreat是activity正在被创建,也就是说此时的UI操作不会更新UI,比如setText操作,所以此时在子线程调用setText不会报线程错误。详解可见Android子线程更新View的探索,在这个方法内我们可以做一些初始化工作。

(2)onRestart需要注意的是:activity正在重新启动,一般情况下,activity从不可见状态到可见状态,onRestart才会被调用,但是一定要注意的是一般来说这是用户行为导致activity不可见的时候,此时变为可见的时候才会调用onRestart,这里所说的用户行为就是用户按home键,或者进入“新”的activity。这样的操作会使activity先执行onPause,后执行onStop,这样回到这个activity会调用onRestart。为什么我这里强调说用户行为导致的不可见状态,等下我会说。。。。

(3)onStart的时候,activity才可见,但是没有出现在前台,无法与用户交互

(4)onResume的时候,activity已经可见,并且出现在前台开始活动,与onStart相比,activity都已经可见,但是onStart的时候activity还在后台,onResume才显示在前台

(5)onPause主要注意的是:此时的activity正在被停止,接下来马上调用onStop。特殊情况下快速回到该activity,onStop不会执行,会去执行onResume。

一般在这个生命周期内做存储数据、停止动画工作,但不能太耗时。
为什么特殊强调呢,因为该activity的onPause执行完了,才回去执行新的activity的onResume,一旦耗时,必然会拖慢新的activity的显示。

(6)onStop:此时的activity即将停止。在这里可以做稍微重量级的操作,同样也不能耗时。

(7)onDestroy:此时的activity即将被回收,在这里会做一些回收工作和最终资源释放。

<think>好的,我现在需要帮助用户了解如何使用Android DataBinding。根据用户提供的引用内容,我需要整理一个结构清晰的教程。首先,我要确定DataBinding的基本配置步骤,因为这是开始使用的前提。然后,布局文件的修改是关键,需要解释如何将传统布局转换为DataBinding支持的格式。接下来,数据绑定的部分,用户可能需要知道如何创建数据模型并将其与UI绑定,引用中的User类示例和BindingAdapter的使用都是重点。此外,用户可能对在Activity和Fragment中的不同用法感兴趣,比如在Activity中使用DataBindingUtil.setContentView,而在Fragment中使用inflate方法。我还需要提到数据绑定的优势,比如减少样板代码,以及处理复杂数据的方法,比如使用@BindingAdapter自定义属性。最后,生成相关问题可以帮助用户深入理解,比如性能优化或与LiveData的结合。需要确保所有步骤都符合引用内容,并且语法正确,使用中文回答,行内公式用$...$,独立公式用$$...$$,不过在这个问题中可能公式较少,但要注意LaTeX的正确使用。检查是否有遗漏的步骤,例如启用DataBinding的Gradle配置,绑定变量的设置,以及事件处理的方法。确保每个部分都有对应的引用标注,比如在Activity和Fragment中的用法分别引用[^2]和[^1]。最后,生成的相关问题要覆盖用户可能感兴趣的扩展方向,如性能、优化、应用场景等。</think>### Android DataBinding 使用教程 #### 1. **启用DataBinding** 在模块的$build.gradle$文件中添加配置: ```groovy android { ... dataBinding { enabled = true } } ``` 同步项目后,系统会自动生成与布局文件对应的绑定类。 #### 2. **修改布局文件** 将传统XML转换为DataBinding格式: ```xml <!-- activity_main.xml --> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.User" /> </data> <LinearLayout...> <TextView android:text="@{user.name}" // 直接绑定变量 .../> <ImageView app:imageUrl="@{user.avatarUrl}" // 自定义属性绑定 .../> </LinearLayout> </layout> ``` 布局根标签需改为$<layout>$,并通过$<data>$定义变量[^3]。 #### 3. **数据绑定实现** - **数据模型类**(例如$User$)需使用可观察机制(如$BaseObservable$或$LiveData$): ```java public class User extends BaseObservable { private String name; @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); // 触发UI更新 } } ``` - **在Activity中绑定数据**: ```java ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); User user = new User(); user.setName("John Doe"); binding.setUser(user); // 关键绑定语句 ``` - **在Fragment/Adapter中使用**: ```java ListItemBinding binding = DataBindingUtil.inflate( LayoutInflater.from(context), R.layout.list_item, parent, false ); binding.setVariable(BR.item, dataItem); // BR.item对应布局中定义的变量名[^1] ``` #### 4. **处理复杂绑定** - **自定义属性**:通过$@BindingAdapter$实现网络图片加载等逻辑: ```java @BindingAdapter("imageUrl") public static void bindImageUrl(ImageView view, String url) { Glide.with(view).load(url).into(view); // 使用第三方库加载图片[^4] } ``` - **事件绑定**:在布局中直接绑定点击事件: ```xml <Button android:onClick="@{() -> viewModel.onButtonClick()}" .../> ``` #### 5. **优势与注意事项** - **优势**:减少$findViewById$调用,UI更新自动化,代码可读性提升[^3] - **注意**:避免在布局中编写复杂逻辑,建议与ViewModel或Presenter模式结合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值