浅谈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即将被回收,在这里会做一些回收工作和最终资源释放。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值