Android 单Activity纯Fragment应用

原创 2016年08月31日 16:56:42

最近做了一个项目,要求全部使用Fragment去实现,就项目中的技术写点什么,希望帮助到大家:

Fragment简单的一些用法我也就不在啰嗦了,就捡终点的说:

1. 首先关于Fragment的初始化工作,我没有使用newInstance这种做法,而是在Activity加载的时候,统一做初始化Fragment fragment = new Fragment(),实际上跟newInstance实现的效果一样


2. 项目中的主页是4个Tab,每个Tab对应一个Fragment,我的布局是用RelativeLayout,底层是主页的布局,上边是单独的一个FrameLayout覆盖在上边,布局文件如下:

<RelativeLayout
    android:id="@+id/rootview"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F7F4F2"
    android:orientation="vertical">

    <include android:id="@+id/title_layout" layout="@layout/activity_home_title_bar"/>

    <RadioGroup
        android:id="@+id/tab_radio_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/common_bgColor"
        android:orientation="horizontal"
        android:paddingBottom="2dp"
        android:paddingTop="2dp">

        <RadioButton
            android:id="@+id/order_btn"
            android:layout_width="0px"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawablePadding="1dp"
            android:drawableTop="@drawable/selector_order_selected"
            android:gravity="center"
            android:text="信件"
            android:textSize="10dp"
            android:textColor="@drawable/selector_order_tx_selected"/>

        <RadioButton
            android:id="@+id/new_order_btn"
            android:layout_width="0px"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="false"
            android:drawablePadding="1dp"
            android:drawableTop="@drawable/selector_newtast_selected"
            android:gravity="center"
            android:text="世界"
            android:textSize="10dp"
            android:textColor="@drawable/selector_order_tx_selected"/>

        <RadioButton
            android:textSize="10dp"
            android:id="@+id/record_order_btn"
            android:layout_width="0px"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="false"
            android:drawablePadding="1dp"
            android:drawableTop="@drawable/selector_recorder_selected"
            android:gravity="center"
            android:text="社区"
            android:textColor="@drawable/selector_order_tx_selected"/>
    </RadioGroup>

    <FrameLayout
        android:layout_below="@+id/title_layout"
        android:id="@+id/fragment_content"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/tab_radio_layout"
       />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="0.5dp"
        android:layout_above="@+id/tab_radio_layout"
        android:background="#D1D1D1"/>

    <FrameLayout
        android:id="@+id/fragment_real_content"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
       />

</RelativeLayout>

3.主页的逻辑相信大家都会做,就说下页面跳转吧,我使用的add Fragment,同时addToBackStack(用途大家应该都知道,就是跟按下返回键的效果一样),代码如下
    public void switchDetailFragment(Fragment fragment, Bundle bundle) {
      
        if (fragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        }
        fragment.setArguments(bundle);
        getSupportFragmentManager().beginTransaction().add(R.id.fragment_real_content, fragment,
                fragment.getClass().getSimpleName())
                .addToBackStack(fragment.getClass().getSimpleName())
                .commit();

    }
这里判断isAdded是为了防止Fragment重复加载抛异常,页面跳转就是这样,同时可以像Activity一样传参数

4. 关于Fragment的Back事件,如果主动调back方法也就是你有一个back button点击的话,那么你可以这样:

getActivity().getSupportFragmentManager().popBackStack()或者getActivity().onBackPressed()效果一样

5.关于Fragment回退栈管理:
 获取回退栈里的Fragment个数可以这样:
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
如果想获取回退栈顶层的Fragment可以这样:
String currentFragmentBackStack = getSupportFragmentManager().getBackStackEntryAt(backStackCount - 1).getName();
如果想做点击2次退出可以这样:
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
Log.d("onBackPressed", "onBackPressed backStackCount:" + backStackCount);
if (backStackCount <= 0) {
    if ((System.currentTimeMillis() - mExitTime) > 2000) {
        Toast.makeText(this, "再按一次,退出程序。", Toast.LENGTH_SHORT).show();
        mExitTime = System.currentTimeMillis();
    } else {
        finish();
    }
    return;
}
6.关于Fragment的回收问题:
我是判断Activity的
onCreate(Bundle savedInstanceState)里的savedInstanceState是否为空,然后做Fragment的remove操作,移除所有的Fragment,再重新加载Fragment
if(savedInstanceState != null ){
Fragment loginFragment = getSupportFragmentManager().findFragmentByTag("LoginFragment");
if (loginFragment != null) {
    getSupportFragmentManager().beginTransaction().remove(loginFragment).commit();
}
同上,吧所有的Fragment都remove掉,再重新走Activity的初始化方法

}

7. 解决Java.lang.IllegalStateException: Fragment already active
先把当前的fragment移除掉,保证栈中不存在多个fragment实例,然后重新new一个对象,再传递参数
Fragment already active
//这里也可以解决Fragment already added问题
if (fragment.isAdded()) {
    getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
if(fragment instanceof MailDetailFragment){
    fragment = new MailDetailFragment();
}
fragment.setArguments(bundle);

补充几个很重要的方法:
1. commit与commitAllowingStateLoss: 你只能在activity存储它的状态(当用户要离开activity时)之前调用commit(),如果在存储状态之后调用commit(),将会抛出一个异常。
 这是因为当activity再次被恢复时commit之后的状态将丢失。如果丢失也没关系,那么使用commitAllowingStateLoss()方法。

 其次FragmentTransaction是异步的,也就是说你commit或者commitAllowingStateLoss并不是立即执行的,如果想要立即执行这个等待中的操作,
 就要调用这个方法 getSupportFragmentManager().executePendingTransactions();

2. 处理Fragment isAdded跟Fragment already active异常:
    if (mTabFragment.isAdded()) {
        getSupportFragmentManager().beginTransaction().remove(mTabFragment).commitAllowingStateLoss();
        getSupportFragmentManager().executePendingTransactions();
        getSupportFragmentManager().beginTransaction().add(R.id.container,
            mTabFragment, mTabFragment.getClass().getSimpleName()).commitAllowingStateLoss();
    } else {
        getSupportFragmentManager().beginTransaction().add(R.id.container,
            mTabFragment, mTabFragment.getClass().getSimpleName()).commitAllowingStateLoss();
    }

好了,就讲到这里,感觉讲的不是很清楚,有问题可以给我留言,也可以加QQ756033860一起探讨。。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

基于ijkplayer的视频播放器,仿Bilibili客户端,集成沉浸式全屏、弹幕、触屏控制、视频源切换等功能

该视频播放器基于Bilibili的开源项目ijkplayer做的,是在github上的demo基础上搭建了个播放界面,如果你之前有研究过这个demo代码,那你看这个库对你来说就非常简单了。至于还不知道...

一个Activity管理多个Fragment切换

先放效果图。有些时候需要整个页面改变,但是又没必要创建一个新的Activity,这时候可以使用这个方法。大致思路是,创建的第一个界面为主界面,通过这个界面打开其它的Fragment。主界面的Fragm...

单Activity多Fragment模式快速构建一个App

前言 自从除了Fragment之后,我便对它情有独钟。从我开始的学习,到现在我做了多个app,我一直在使用Fragment,并且形成了我自己的app架构模式“单Activity多Fragment”,...

超级封装让你的项目搭建事半功倍-单Activity多Fragment模式

上篇文章介绍了单Activity多Fragment模式去构建一个项目的简单框架,这种模式可以带给我们诸多好处。本篇我将在上一篇那个模式的基础上对这个app里面的一些类进行封装,可以让我们的项目搭建事半...

Fragment详解之三——管理Fragment(1)

前言:follow your heart,be your own king

android之fragment的两种使用方式(add和replace方式切换)

使用过app的人都知道,几乎所有的app都用到fragment进行首页分割,还有的加上了Indicator或者Tablayout或者Viewpager之类的结合使用。总之,fragment是必须掌握的...
  • gsw333
  • gsw333
  • 2016-07-08 11:56
  • 24366

Kotlin 资源大全

官网及文档 Kotlin 官网Kotlin 文档Kotlin 中文文档Kotlin on GitHub 中文社区 掘金技术社区 教程 & 文章 视频教程 ...

【Android】Android开发之Activity的管理类,结束关闭指定的Activity,单例模式封装

作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing长期维护的Android项目,里面...

单Activity架构,丝滑般享受

注:自己写的手记,取下来整理到博客中,让更多人能方便看到 大多数正在学习的同学,往往是从Activity的生命周期以及Activity间的跳转开始展开学习的。而大部分的Android应用,其业务...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)