Fragment内存回收后重叠及恢复数据问题

从源码角度分析,为什么会发生Fragment重叠?

package com.mine.fragmentdemo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import static com.mine.fragmentdemo.FragmentFactory.F1;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tv1;
    private TextView tv2;
    private TextView tv3;
    private FragmentManager mFragmentManager;
    private Fragment mFragment1;
    private Fragment mFragment2;
    private Fragment mFragment3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = (TextView) findViewById(R.id.tv1);
        tv2 = (TextView) findViewById(R.id.tv2);
        tv3 = (TextView) findViewById(R.id.tv3);
        tv1.setOnClickListener(this);
        tv2.setOnClickListener(this);
        tv3.setOnClickListener(this);
        /*
        * Fragment重叠原因一
        * 1.Activity横竖屏切换(或者后台的Activity由于内存不足,被回收),导致Activity重走生命周期
        * 2.但是FragmentManager会保存之前的Fragment,当页面恢复时,会把这些Fragment都显示出来
        * 3.此时,在Activity的onCreate里面你再次new Fragment时并且add了一次,会导致Fragment的重叠
        * 4.解决方法是第一次时直接new,第二次页面恢复后,要使用mFragmentManager通过Tag来取得,
        * 第一次和第二次的判断标志就是savedInstanceState是否为null(内存回收Activity时,会把数据保存在savedInstanceState里)
        * */

//        ★全局用一个mFragmentManager
        mFragmentManager = getSupportFragmentManager();
        if (savedInstanceState == null) {
            mFragment1 = FragmentFactory.createFragment(F1);
//           ★ 为什么第一个fragment在添加的时候用的是replace而不是add?
//            防止回退到首页的时候显示Activity的空的FrameLayout(这是指有回退栈情况,没回退栈用add也不会出现空白,因为已经直接退出了)(★★★其实最还是,直接在默认第一个加载的Fragment不要加入回退栈就好了)
            selectFragment1(mFragment1);
        } else {
//            先使用mFragmentManager通过Tag来取得,只要他add过,就给他添加了Tag
//            否则直接重写创建一个Fragment的话,会导致重叠
            mFragment1 = mFragmentManager.findFragmentByTag(Fragment1.class.getName());
            if (mFragment1 == null) {
                mFragment1 = FragmentFactory.createFragment(FragmentFactory.F1);

            }
            mFragment2 = mFragmentManager.findFragmentByTag(Fragment2.class.getName());
            if (mFragment2 == null) {
//                有可能获得为空,因为你还没与把mFragment2添加,还没有给其设置Tag,所以这里为空
                mFragment2 = FragmentFactory.createFragment(FragmentFactory.F2);

            }

            mFragment3 = mFragmentManager.findFragmentByTag(Fragment3.class.getName());
            if (mFragment3 == null) {
                mFragment3 = FragmentFactory.createFragment(FragmentFactory.F3);

            }


            position = savedInstanceState.getInt("position");
            switch (position) {
                case 1:
                    selectFragment(mFragment1);
                    break;

                case 2:
                    selectFragment(mFragment2);
                    break;

                case 3:
                    selectFragment(mFragment3);
                    break;
            }

        }

    }


    //记录Fragment的位置
    private int position = 1;

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //记录当前的position
        outState.putInt("position", position);
        Log.e("Ccc", position + "dfssf");
//        ★★★★★★★★别忘了下下面的super.onSave,否则会报错
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv1:
                if (mFragment1 == null) {
                    mFragment1 = FragmentFactory.createFragment(FragmentFactory.F1);
                }
                selectFragment(mFragment1);
//                    记录下当前是哪一个Fragment,
//                    方便重新走Activity生命周期时,获取其死亡时的位置
                position = 1;
                break;

            case R.id.tv2:
                if (mFragment2 == null) {
                    mFragment2 = FragmentFactory.createFragment(FragmentFactory.F2);
                }
                selectFragment(mFragment2);
                position = 2;

                break;

            case R.id.tv3:
                if (mFragment3 == null) {
                    mFragment3 = FragmentFactory.createFragment(FragmentFactory.F3);
                }
                selectFragment(mFragment3);
                position = 3;

                break;
        }
    }

    private void selectFragment(Fragment fragment) {
        FragmentTransaction transaction = mFragmentManager.beginTransaction();
        hideAll(transaction);

        if (!fragment.isAdded()) {
            transaction.add(R.id.fl, fragment, fragment.getClass().getName());
//            transaction.addToBackStack(null);

        }
        Log.e("qqq",mFragmentManager.getBackStackEntryCount()+"qqq");

        transaction.show(fragment).commit();
        Log.e("qqq",mFragmentManager.getBackStackEntryCount()+"hoe");

    }

    private void selectFragment1(Fragment fragment) {
        FragmentTransaction transaction = mFragmentManager.beginTransaction();

            transaction.replace(R.id.fl, fragment, fragment.getClass().getName()).commit();



    }

    private void hideAll(FragmentTransaction transaction) {
        if (mFragment1 != null) {
//            必须使用同一个transaction,跟add/show时候一样
//            同一个事物进行了所有的add/hide/show,之后统一commit就行了
//            中间不能commit事物,因为一个事物只能是提交一次,重复提交会报错
//            即:每一次点击,生成一个事物,操作完后,提交这个事物
            transaction.hide(mFragment1);
        }

        if (mFragment2 != null) {
            transaction.hide(mFragment2);
        }

        if (mFragment3 != null) {
            transaction.hide(mFragment3);
        }
    }
    /**
     * 手动回退
     */
    public void popBackStack(){
        if (mFragmentManager.getBackStackEntryCount()>0){
            mFragmentManager.popBackStack();
        }else {
            finish();
        }
    }

    @Override
    public void onBackPressed() {
//        super.onBackPressed();屏蔽掉系统的返回事件
        popBackStack();
    }


}

===

package com.mine.fragmentdemo;

import android.support.v4.app.Fragment;

import java.util.HashMap;

/**
 * Created by a on 2017/4/5.
 */
public class FragmentFactory {
    public final static int F1 = 1;
    public final static int F2 = 2;
    public final static int F3 = 3;

    private static HashMap<Integer, Fragment> mFragments = new HashMap<>();


    public static Fragment createFragment(int fragmentName) {
        // 从缓存中取出
        Fragment fragment = mFragments.get(fragmentName);
        if (fragment == null) {
            switch (fragmentName) {

                case F1:
                    fragment = new Fragment1();
                    break;

                case F2:
                    fragment = new Fragment2();

                    break;

                case F3:
                    fragment = new Fragment3();

                    break;
            }
            // 把frament加入到缓存中
            mFragments.put(fragmentName,fragment);
        }

        return fragment;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值