Android Fragemnt重叠

1、闲聊

        今天测试突然给我提出了一个bug,我特么当时就懵逼了!What?什么鬼?写一个项目结构写出来了一个bug!然后我就去看,我越看越懵逼这样写没错啊!我实在看不出来,算了看一下生命周期吧!好吧,写一个测试dome,来打印一下生命周期:

onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{8626570 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{ec4200f #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{5e0689c #2 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{9d97288 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{fab6421 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{701e046 #2 id=0x7f0b006c tab3}
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{2dd30cc #3 id=0x7f0b006c tab1}
onRestoreInstanceState: --------------------
onAttachFragment: --------------------Tab2Fragment{6d41f15 #4 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{907d22a #5 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{6649791 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{a28e6f6 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{20d7af7 #2 id=0x7f0b006c tab3}
onAttachFragment: --------------------Tab1Fragment{d3ecd64 #3 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{5aa1bcd #4 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{b747c82 #5 id=0x7f0b006c tab3}
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{420d4e8 #6 id=0x7f0b006c tab1}
onRestoreInstanceState: --------------------

        自大了,光看肯定看不出毛病的!有了生命周期我们就可以了解原理咯。可以看出来我每次进入后台时都会执行onSaveInstanceState方法,
我每次从后台回到页面时会依次执行:onAttachFragment,onCreate,onSaveInstanceState这三个我需要的方法!到了这里我的想法是onSaveInstanceState这个方法在onAttachFragment,onCreate这两个方法的后面,我个人肯定不愿意在这里取出数据,因为我出现的这个bug是在活动销毁后才会出现的bug!每次肯定会走onCreate,所以我更愿意在onCreate方法中取出数据,但是这个东西的看你们的喜好,onAttachFragment这个方法中取出Fragment也是非常方便的,至少比onCreate方便,如:

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if (null != fragment && fragment instanceof Tab3Fragment) {
        tab3Fragment = (Tab3Fragment) fragment;
    }
    Log.d(TAG, "onAttachFragment: --------------------" + fragment);
}

在看一下在onCreate中取数据:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_fragment);
    if (null != savedInstanceState) {
        FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
        if (null != fragment && fragment instanceof Tab1Fragment) {
            tab1Fragment = (Tab1Fragment) fragment;
        }
    }
}

        可以看出来了吧,onCreate方法中要多一个步奏来获取fragment,好了就聊到这儿!我们开始说具体怎样解决这个问题。

2、解决问题

        解决问题的方法肯定不止一种,这里我只说一种:我这里在使用FragmentTransaction(Fragment管理器)的时候,为每一个需要添加显示的Fragment打上一个 #tag 标记,再退出后台情况下,活动被销毁后,通过FragmentTransaction去取出对应 tag 存储的 Fragment,当然我这儿还存了一个索引值:index(退出后台时,显示的第几个fragment)!那就上代码了:


退出时保存 index:
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(tabs[0], index);
    Log.d(TAG, "onSaveInstanceState: --------------------");
}

从新进入页面时,取出状态及fragment:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_fragment);
    Log.d(TAG, "onCreate: --------------------");
    if (null != savedInstanceState) {
        index = savedInstanceState.getInt(tabs[0], 1);
        FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
        if (null != fragment && fragment instanceof Tab1Fragment) {
            tab1Fragment = (Tab1Fragment) fragment;
        }
        fragment = fragmentManager.findFragmentByTag(tabs[2]);
        if (null != fragment && fragment instanceof Tab2Fragment) {
            tab2Fragment = (Tab2Fragment) fragment;
        }
        fragment = fragmentManager.findFragmentByTag(tabs[3]);
        if (null != fragment && fragment instanceof Tab3Fragment) {
            tab3Fragment = (Tab3Fragment) fragment;
        }
    }
    showTab(index);
    init();
}

我们现在再来看一看生命周期:
onCreate: --------------------
onAttachFragment: --------------------Tab1Fragment{c577bb3 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{61d116e #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{ec4200f #2 id=0x7f0b006c tab3}
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{facae2b #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{9d97288 #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{fab6421 #2 id=0x7f0b006c tab3}
onCreate: --------------------
onRestoreInstanceState: --------------------
onSaveInstanceState: --------------------
onAttachFragment: --------------------Tab1Fragment{6d41f15 #0 id=0x7f0b006c tab1}
onAttachFragment: --------------------Tab2Fragment{907d22a #1 id=0x7f0b006c tab2}
onAttachFragment: --------------------Tab3Fragment{d9781b #2 id=0x7f0b006c tab3}
onCreate: --------------------
onRestoreInstanceState: --------------------

        现在这个东西看着就非常清晰了吧!再也没有多次创建fragment了,那么这问题就算圆满解决了!

3、源码

public class TestFragmentActivity extends AppCompatActivity {
    private static final String TAG = "TestFragmentActivity";
    private Tab1Fragment tab1Fragment;
    private Tab2Fragment tab2Fragment;
    private Tab3Fragment tab3Fragment;
    private int index = 1;
    private String[] tabs = {"index", "tab1", "tab2", "tab3"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_fragment);
        Log.d(TAG, "onCreate: --------------------");
        if (null != savedInstanceState) {
            index = savedInstanceState.getInt(tabs[0], 1);
            FragmentManager fragmentManager = getFragmentManager();
            Fragment fragment = fragmentManager.findFragmentByTag(tabs[1]);
            if (null != fragment && fragment instanceof Tab1Fragment) {
                tab1Fragment = (Tab1Fragment) fragment;
            }
            fragment = fragmentManager.findFragmentByTag(tabs[2]);
            if (null != fragment && fragment instanceof Tab2Fragment) {
                tab2Fragment = (Tab2Fragment) fragment;
            }
            fragment = fragmentManager.findFragmentByTag(tabs[3]);
            if (null != fragment && fragment instanceof Tab3Fragment) {
                tab3Fragment = (Tab3Fragment) fragment;
            }
        }
        showTab(index);
        init();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(tabs[0], index);
        Log.d(TAG, "onSaveInstanceState: --------------------");
    }

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        Log.d(TAG, "onAttachFragment: --------------------" + fragment);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onRestoreInstanceState: --------------------");
    }

    private void init() {
        findViewById(R.id.tv_tab1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(1);
            }
        });
        findViewById(R.id.tv_tab2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(2);
            }
        });
        findViewById(R.id.tv_tab3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showTab(3);
            }
        });
    }

    private void showTab(int index) {
        this.index = index;
        // 开启一个Fragment事务
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        hideFragment(transaction);
        switch (index) {
            case 1:
                if (null == tab1Fragment) {
                    tab1Fragment = new Tab1Fragment();
                    transaction.add(R.id.fragment, tab1Fragment, tabs[index]);
                } else {
                    transaction.show(tab1Fragment);
                }
                break;
            case 2:
                if (null == tab2Fragment) {
                    tab2Fragment = new Tab2Fragment();
                    transaction.add(R.id.fragment, tab2Fragment, tabs[index]);
                } else {
                    transaction.show(tab2Fragment);
                }
                break;
            case 3:
                if (null == tab3Fragment) {
                    tab3Fragment = new Tab3Fragment();
                    transaction.add(R.id.fragment, tab3Fragment, tabs[index]);
                } else {
                    transaction.show(tab3Fragment);
                }
                break;
        }
        transaction.commit();
    }

    private void hideFragment(FragmentTransaction transaction) {
        if (null != tab1Fragment) {
            transaction.hide(tab1Fragment);
        }
        if (null != tab2Fragment) {
            transaction.hide(tab2Fragment);
        }
        if (null != tab3Fragment) {
            transaction.hide(tab3Fragment);
        }
    }
}

        至此问题已解决!有问题即时反馈,谢谢!

你可能感兴趣的:(bug管理,进阶)