关于Activity和Fragment的一些问题

概述

Activity和Fragment是Android开发中经常需要用到的,但是在使用的过程中有些细节性的问题很多人没有在意,今天我们就去带大家看看几个比较值得研究的地方。

实现

1.replace进行Fragment的切换,这样会重新实例化当前fragment。重新加载一遍数据,非常消耗性能和用户的数据流量,如果不是项目需求的话,不建议采用这种方式。

这里写图片描述

 public void switchFragment(Fragment targetFragment){
        if(targetFragment == null) return;
        getSupportFragmentManager().beginTransaction()
        .replace(R.id.fl_content, targetFragment).commit();
    }

2.add,hide,show切换fragment,不会重新实例化当前fragment

这里写图片描述

从图中我们可以看出,每个Fragment确实只是初始化了一次,代码如下

public class MainActivity extends FragmentActivity implements RadioGroup.OnCheckedChangeListener{
    private Fragment currentFragment;//当前fragment
    private FragmentOne fragmentOne;
    private FragmentTwo fragmentTwo;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rg_bottom);
        radioGroup.setOnCheckedChangeListener(this);
        currentFragment = new FragmentOne();
        //默认选中第一个Fragment
        ((RadioButton)radioGroup.getChildAt(0)).setChecked(true);
    }

    public void start(View view){
        startActivity(new Intent(this,SecondActivity.class));
    }

    @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        switch (checkedId){
            case R.id.rb_first:
                if(fragmentOne == null) {
                    fragmentOne = new FragmentOne();
                }
                switchFragment(fragmentOne);
                break;
            case R.id.rb_second:
                if(fragmentTwo == null) {
                    fragmentTwo = new FragmentTwo();
                }
                switchFragment(fragmentTwo);
                break;
        }
    }
        public void switchFragment(Fragment targetFragment){
            if(targetFragment!=null){
                if(targetFragment == currentFragment){
                    return;
                }
            }
            FragmentTransaction transaction = getSupportFragmentManager()
                    .beginTransaction();
            if (!targetFragment.isAdded()) {
                transaction
                        .hide(currentFragment)
                        .add(R.id.fl_content, targetFragment)
                        .commit();
                System.out.println("还没添加呢");
            } else {
                transaction
                        .hide(currentFragment)
                        .show(targetFragment)
                        .commit();
                System.out.println("添加了( ⊙o⊙ )哇");
            }
            currentFragment = targetFragment;
    }
}

3.加入有这样的需求,每次切换fragment时都需要做一些操作,那么这时候我们就需要监听fragment的切换了。这时候可以利用onHiddenChanged,两个fragment进行切换的时候,会同时触发这两个fragment的onHiddenChanged方法。

这里写图片描述

4.Fragment重叠问题

这里写图片描述

前提:使用hide,show方法切换fragment
原因:当前Activity销毁的时候,系统会保存Fragment的状态,下次新的Activity重建的时候,无法控制当前fragment,导致fragment无法隐藏,重叠在一起

解决办法:重新当前Activity的onSaveInstanceState方法,注释掉保存状态的代码

@Override
    protected void onSaveInstanceState(Bundle outState) {
        //super.onSaveInstanceState(outState);
    }

这时候再去切换就没有问题了。

5.底部Tab状态显示错误

这里写图片描述

当我们切换到非第一个按钮时,重新销毁当前Activity,此时按钮又会回到第一个选中。

解决办法,在onSaveInstanceState保存当前按钮选中的位置,在Activity重建是从参数中取书这个值,重新为对应位置的按钮设置选中

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rg_bottom);
        radioGroup.setOnCheckedChangeListener(this);
        currentFragment = new FragmentOne();
        //默认选中第一个Fragment
        ((RadioButton)radioGroup.getChildAt(0)).setChecked(true);
        //恢复按钮状态
        if(savedInstanceState!=null){
            index = Integer.parseInt(savedInstanceState.getString("index"));
            ((RadioButton)radioGroup.getChildAt(index)).setChecked(true);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //保存按钮索引位置
        outState.putString("index",String.valueOf(index));
    }

6.setArgument方法的使用

众所周知,我们用setArgument来传递参数,如果使用不当,很可能发生下面的问题

这里写图片描述

原因:java.lang.IllegalStateException: Fragment already active异常主要是使用setArguments()传递参数导致的。
在 Fragment 没有被添加到 FragmentManager 之前,我们可以通过 Fragment.setArguments() 来设置参数,并在 Fragment 中,使用 getArguments() 来取得参数。在 Fragment 被添加到 FragmentManager 后,一旦被使用,我们再次调用 setArguments() 将会导致 java.lang.IllegalStateException: Fragment already active 异常。

正确使用方法

public class FragmentOne extends Fragment{
    private TextView textView;
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_one, null);
        textView = (TextView) view.findViewById(R.id.textview);
        if(getArguments()!=null){
            //取出保存的值
            textView.setText(getArguments().getString("name"));
        }
        return view;
    }
    public static  FragmentOne newInstance(String text){
        FragmentOne fragmentOne = new FragmentOne();
        Bundle bundle = new Bundle();
        bundle.putString("name", text);
        //fragment保存参数,传入一个Bundle对象
        fragmentOne.setArguments(bundle);
        return fragmentOne;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值