Android Fragment 详解 2016 干货

最近看了很多动画和一些效果很好的自定义控件,发现了一件事,就是Android的View层设计思想和古老的JavaSwing是如此的相似。这是在原来的基础上加入了一些输入移动端的生命周期,使其在使用和性能上更好。但是对核心的理解还是可以借鉴一些的。
如果说Activity就是JavaSwing的JFrame那么Fragment 就是在JPanel
一个是容器顶层控件,一个是显示在容器上的中间层控件。
所以这里插一句话,如果感觉自己android写的不溜那么就多看看java的代码。和设计思想吧。android的东西太多都是继承自java或者说就是java的衍生品。无论是顶层容器还是底层容器都是为了放交互容器的。

Fragment的使用
一、布局
大家完全可以把Fragment看成一个轻量级的Activity.为什么轻量,因为他不用在mainfest.xml文件中添加自己.第二他不能直接启动,必须依附(attach)在activity之上。
所以在这布局这一块,Fragment的使用完全可以和activity的布局划等号,设计图怎么画在这里就怎么设计一个 Fragment .

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#00ff00" >  

    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="This is fragment 1"  
        android:textColor="#000000"  
        android:textSize="25sp" />  

</LinearLayout> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#ffff00" >  

    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="This is fragment 2"  
        android:textColor="#000000"  
        android:textSize="25sp" />  

</LinearLayout>  

简单的画了两个布局背景不同,文字区分1和2
二、在Activity中使用
使用方法一:静态加载一个Fragment
第一步把这个 fragment实例化

public class Fragment1 extends Fragment {  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
        return inflater.inflate(R.layout.fragment1, container, false);  
    }  
}  

二和一 ,一样
在onCreateView() 中实现的是

{
    View view=inflater.inflate(R.layout.fragment);//这个View就是父容器在这个布局里的其他控件 好比TextView要依靠他findViewById();
    TextView tv=(TextView)view.findViewById(R.id,textview);
    return view;
}

这样一个 Fragment在View层就创建成功了。
然后打开或新建activity_main.xml作为主Activity的布局文件,在里面加入两个Fragment的引用,使用android:name前缀来引用具体的

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:baselineAligned="false" >  

    <fragment  
        android:id="@+id/fragment1"  
        **android:name="com.example.fragmentdemo.Fragment1"**  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  

    <fragment  
        android:id="@+id/fragment2"  
        **android:name="com.example.fragmentdemo.Fragment2"**  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  

</LinearLayout>  

最后打开或新建MainActivity作为程序的主Activity,里面的代码非常简单,都是自动生成的:

public class MainActivity extends Activity {  

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

}  

这里写图片描述
如我们的设计一样,两个Fragment平分了屏幕

使用方法二:动态添加
这回我们直接在Activity中使用Fragment

public class MainActivity extends Activity {  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        Display display = getWindowManager().getDefaultDisplay();  
        if (display.getWidth() > display.getHeight()) {  
            Fragment1 fragment1 = new Fragment1(); //新建Fragment
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit(); //添加Fragment提交
        } else {  
            Fragment2 fragment2 = new Fragment2();  
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit();  
        }  
    }   
}  

首先,我们要获取屏幕的宽度和高度,然后进行判断,如果屏幕宽度大于高度就添加fragment1,如果高度大于宽度就添加fragment2。动态添加Fragment主要分为4步:
1.获取到FragmentManager,在Activity中可以直接通过getFragmentManager得到。
2.开启一个事务,通过调用beginTransaction方法开启。
3.向容器内加入Fragment,一般使用replace方法实现,需要传入容器的id和Fragment的实例。
4.提交事务,调用commit方法提交。
现在运行一下程序,效果如下图所示:
竖屏显示结果
这里写图片描述`
横屏显示结果
这里写图片描述

在实战中主要使用的是第二种方法使用我们的Fragment.
这里写图片描述
即底部是三个activity切换按钮上面是三个Fragment这里的,这里对Fragment的使用方法就是使用动态加载的方法。

三、Fragment的生命周期 Fragment 就是一个轻量的Activity那么他的声明周期就和Activity非常像了。
生命周期如下:
1.onAttach() 在Fragment和Activity建立关联的时候调用
2.onCreate() 初始化Fragment本身为inflate view做准备
3.onCreateView() 对布局中的所有控件进行初始化 绑定
4.onActivityCreated
5.onStart
6onResume
在按下home之后
1.onPause 程序挂起
2.onStop 当前activity 停止
在返回程序之后
1.onStart 开始
2.onResume 恢复

点击back退出程序
1onPause
2onStop
3onDestoryView Fragment 的View被移除了。
4onDestory
5onDetach Fragment和Activiy解除关联的时候调用
注:此处并没有onRestart()方法!

三、Fragment通信
这里的通信主要分为
fragment->fragment 通过getActivity()为桥梁进行通信
Activity->fragment
fragment-activity 最简单 所有activity 之间的通信方法这种时候都可以用

如在之前Fragment2中添加一个button那么我们需要调用其他相关的Fragment是如何实现的那。

public class Fragment2 extends Fragment {  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
        return inflater.inflate(R.layout.fragment2, container, false);  
    }  

    @Override  
    public void onActivityCreated(Bundle savedInstanceState) {  
        super.onActivityCreated(savedInstanceState);  
        Button button = (Button) getActivity().findViewById(R.id.button);  
        button.setOnClickListener(new OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                TextView textView = (TextView) getActivity().findViewById(R.id.fragment1_text);  
                Toast.makeText(getActivity(), textView.getText(), Toast.LENGTH_LONG).show();  
            }  
        });  
    }    
}  

当点击按钮的时候就会在Toast中显示Fragment1中的内容。
当然两个Fragment需要使用一个共同的activity父容器。

最后分享一些使用心得
补充知识点:
1、什么是FragmentTransaction?
使用Fragment时,可以通过用户交互来执行一些动作,比如增加、移除、替换等。
所有这些改变构成一个集合,这个集合被叫做一个transaction。

可以调用FragmentTransaction中的方法来处理这个transaction,并且可以将transaction存进由activity管理的back stack中,这样用户就可以进行fragment变化的回退操作。

可以这样得到FragmentTransaction类的实例:

1.FragmentManager  mFragmentManager = getSupportFragmentManager();
2.FragmentTransaction  mFragmentTransaction = mFragmentManager.beginTransaction();

在多个 Fragment 之间进行切换的时候
replace()和hide的区别
首先replace 是代替,之前的Fragment会被清空掉,在再次切换回来的时候会进行重新加载。而hide是将之前的一个fragment 进行隐藏,将新的fragment 叠在上面进行显示.等在次调用的时候进行显示。不需要重新加载。测试这个最简单的方法就是 设计两个fragment 在同一位置上放一个按钮,一个有监听一个没有,但现实没有监听的按钮点击按钮的时候会响应一号按钮的监听事件。

另外一个对于 FragmentTransaction对象在commit之后就会失效。所以建议直接使用fragmentManager.beginTransaction() 这样就不会产生失效的问题了。

commit 于commitAllowingStateLoss();的区别
简单来说就是避免报错。
他们都调用了commitInternal
public int commit() {
return commitInternal(false);
}

public int commitAllowingStateLoss() {
return commitInternal(true);
}
这个两个方法区别就在传参判断后的处理方法checkStateLoss
当使用commit方法时,系统将进行状态判断,如果状态(mStateSaved)已经保存,将发生”Can not perform this action after onSaveInstanceState”错误。
如果mNoTransactionsBecause已经存在,将发生”Can not perform this action inside of ” + mNoTransactionsBecause错误

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值