申请后重叠隐藏片段杀死后恢复 [英] Overlapping hidden fragments after application gets killed and restored

查看:104
本文介绍了申请后重叠隐藏片段杀死后恢复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我片段之间的切换通过的隐藏的最后一个片段和添加一个新的(见code以下) - 将其添加到返回-stack 作为良好。通过这种方式,用户可以快速的片段之间无需重新加载的片段数据交换。

这工作得很好,直到应用程序是(场景:用户使用其他一些应用程序和我的应用程序得到坚持和杀死)。

当用户打开应用程序,它是恢复和所有的片段显示 - 重叠另一个

问:如何恢复的片段被他们隐藏的状态恢复也许我错过了一些标志?某处?也许,对于片段之间快速切换一个更好的解决方案(无需重新加载数据)?

-

样品$ C $加碎片了C后,点击某个地方调用多次与不同的片段:

  FragmentTransaction fragmentTransaction = getFragmentManager()的BeginTransaction();
fragmentTransaction.hide(lastFragment);
fragmentTransaction.add(newFragment);
fragmentTransaction.addToBackStack(空);
fragmentTransaction.commit();
lastFragment = newFragment;
 

解决方案

希望有人找到一个更好的解决方案。我等的人之前,我接受我的解决方案:

在一般情况下,我用生成的标签找到的取消隐藏碎片和隐藏它们。

在细节,我生成每个片段(StackEntry)的唯一标签和堆叠标签,片段本身得到堆积。我坚持堆在bundel并加载它,当应用程序,以便用它来continure得到恢复。然后,我用的标签列表中找到的所有的取消隐藏片段,并隐藏他们 - 除了最后一个

继承人样品code:

 公共类FragmentActivity延伸活动{

    私有静态最后弦乐FRAGMENT_STACK_KEY =FRAGMENT_STACK_KEY;

    私人堆叠式和LT; StackEntry> fragmentsStack =新的堆栈< StackEntry>();

    公共FragmentActivity(){
    }

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        的setContentView(R.layout.content_frame);

        如果(savedInstanceState == NULL){
            //初始化的第一次 - 不是恢复
            // ...
        } 其他 {
            序列化序列化= savedInstanceState.getSerializable(FRAGMENT_STACK_KEY);
            如果(序列化!= NULL){
                //解决方法Android的错误。
                // 看到: http://stackoverflow.com/questions/13982192/when-using-an-android-bundle-why-does-a-serialised-stack-deserialise-as-an-arra
                //而如下:https://$c$c.google.com/p/android/issues/detail ID = 3847
                @燮pressWarnings(未登记)
                名单< StackEntry> ArrayList的=(名单< StackEntry>)序列化;
                fragmentsStack =新的堆栈< StackEntry>();
                fragmentsStack.addAll(数组列表);
            }

            //隐藏所有恢复的片段,而不是最后一个
            如果(fragmentsStack.size()→1){
                FragmentTransaction fragmentTransaction = getFragmentManager()的BeginTransaction()。
                的for(int i = 0; I< fragmentsStack.size() -  1;我++){
                    串fragTag = fragmentsStack.get(ⅰ).getFragTag();
                    片段片段= getFragmentManager()findFragmentByTag(fragTag)。
                    fragmentTransaction.hide(片段);
                }
                fragmentTransaction.commit();
            }
        }
        getFragmentManager()。addOnBackStackChangedListener(新OnBackStackChangedListener(){
            @覆盖
            公共无效onBackStackChanged(){
                片段lastFragment = getLastFragment();
                如果(lastFragment.isHidden()){
                    FragmentTransaction fragmentTransaction = getFragmentManager()的BeginTransaction()。
                    fragmentTransaction.show(lastFragment);
                    fragmentTransaction.commit();
                }
            }
        });
    }

    私人片段getLastFragment(){
        如果(fragmentsStack.isEmpty())返回NULL;
        字符串fragTag = fragmentsStack.peek()getFragTag()。
        片段片段= getFragmentManager()findFragmentByTag(fragTag)。
        返回片段;
    }

    @覆盖
    保护无效的onSaveInstanceState(包outState){
        super.onSaveInstanceState(outState);
        outState.putSerializable(FRAGMENT_STACK_KEY,fragmentsStack);
    }

    @覆盖
    公共无效onBack pressed(){
        如果(!fragmentsStack.isEmpty()){
            fragmentsStack.pop();
        }
    }

    公共无效switchContent(片段片段){
        FragmentTransaction fragmentTransaction = getFragmentManager()的BeginTransaction()。
        片段lastFragment = getLastFragment();
        如果(lastFragment!= NULL){
            fragmentTransaction.hide(lastFragment);
        }
        字符串fragTag;
        如果(fragment.isAdded()){
            fragmentTransaction.show(片段);
            fragTag = fragment.getTag();
        } 其他 {
            fragTag = Long.toString(System.currentTimeMillis的());
            fragmentTransaction.add(R.id.content_frame,片段,fragTag);
        }
        如果(!isFirstFragment()){
            //添加到backstack只有第一个内容片段,而不是之前的状态(即没有任何关系)
            fragmentTransaction.addToBackStack(空);
        }
        fragmentTransaction.commit();

        fragmentsStack.push(新StackEntry(fragTag));
    }

    公共布尔isFirstFragment(){
        返回fragmentsStack.size()== 0;
    }

    私有静态类StackEntry实现Serializable {
        私有静态最后长的serialVersionUID = -6162805540320628024L;

        私人字符串fragTag = NULL;
        公共StackEntry(字符串fragTag){
            超();
            this.fragTag = fragTag;
        }
        公共字符串getFragTag(){
            返回fragTag;
        }
    }


    公共静态类意图扩展android.content.Intent {
        公众意向(上下文packageContext){
            超(packageContext,FragmentActivity.class);
        }
    }
}
 

I'm switching between fragments by hiding the last fragment and adding a new one (See code below) - adding it to the back-stack as well. This way, users can quickly switch between the fragments without reloading the fragment data.

This works well until the app is killed (Scenario: users uses several other apps and my app is getting persisted and killed).

When a user opens the app, it is being restored and all the fragments are shown - overlapping one another.

Question: How can the restored fragments be restored with their hidden state? Perhaps I'm missing some flag? somewhere? Perhaps there is a better solution for fast switching between fragments (without reloading the data)?

Sample code of adding fragments - invoked several times with different fragments upon clicking somewhere:

FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.hide(lastFragment);
fragmentTransaction.add(newFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
lastFragment = newFragment;

解决方案

Hope somebody finds a better solution. I'll wait for one before I accept my solution:

In general, I use generated tags to find the unhidden fragments and hide them.

In details, I generate a unique tag for each fragment (StackEntry) and stack the tags as the fragments themselves get stacked. I persist the stack in the bundel and load it when the app gets restored in order to continure using it. Then I use the list of tags to find all of the unhidden fragments and hide them - except for the last one.

Heres sample code:

public class FragmentActivity extends Activity {

    private static final String FRAGMENT_STACK_KEY = "FRAGMENT_STACK_KEY";

    private Stack<StackEntry> fragmentsStack = new Stack<StackEntry>();

    public FragmentActivity() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.content_frame);

        if (savedInstanceState == null) {
            // Init for the first time - not restore
            // ...
        } else {
            Serializable serializable = savedInstanceState.getSerializable(FRAGMENT_STACK_KEY);
            if (serializable != null) {
                // Workaround Android bug.
                // See: http://stackoverflow.com/questions/13982192/when-using-an-android-bundle-why-does-a-serialised-stack-deserialise-as-an-arra
                // And: https://code.google.com/p/android/issues/detail?id=3847
                @SuppressWarnings("unchecked")
                List<StackEntry> arrayList = (List<StackEntry>) serializable;
                fragmentsStack = new Stack<StackEntry>();
                fragmentsStack.addAll(arrayList);
            }

            // Hide all the restored fragments instead of the last one
            if (fragmentsStack.size() > 1) {
                FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
                for (int i = 0; i < fragmentsStack.size()-1; i++) {
                    String fragTag = fragmentsStack.get(i).getFragTag();
                    Fragment fragment = getFragmentManager().findFragmentByTag(fragTag);
                    fragmentTransaction.hide(fragment);
                }
                fragmentTransaction.commit();
            }
        }
        getFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                Fragment lastFragment = getLastFragment();
                if (lastFragment.isHidden()) {
                    FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
                    fragmentTransaction.show(lastFragment);
                    fragmentTransaction.commit();
                }
            }
        });
    }

    private Fragment getLastFragment() {
        if (fragmentsStack.isEmpty()) return null;
        String fragTag = fragmentsStack.peek().getFragTag();
        Fragment fragment = getFragmentManager().findFragmentByTag(fragTag);
        return fragment;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(FRAGMENT_STACK_KEY, fragmentsStack);
    }

    @Override
    public void onBackPressed() {
        if (!fragmentsStack.isEmpty()) {
            fragmentsStack.pop();
        }
    }

    public void switchContent(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        Fragment lastFragment = getLastFragment();
        if (lastFragment != null) {
            fragmentTransaction.hide(lastFragment);
        }
        String fragTag;
        if (fragment.isAdded()) {
            fragmentTransaction.show(fragment);
            fragTag = fragment.getTag();
        } else {
            fragTag = Long.toString(System.currentTimeMillis());
            fragmentTransaction.add(R.id.content_frame, fragment, fragTag);
        }
        if (!isFirstFragment()) {
            // Add to backstack only the first content fragment and not the state before (that has nothing)
            fragmentTransaction.addToBackStack(null);
        }
        fragmentTransaction.commit();

        fragmentsStack.push(new StackEntry(fragTag));
    }

    public boolean isFirstFragment() {
        return fragmentsStack.size() == 0;
    }

    private static class StackEntry implements Serializable {
        private static final long serialVersionUID = -6162805540320628024L;

        private String fragTag = null;
        public StackEntry(String fragTag) {
            super();
            this.fragTag = fragTag;
        }
        public String getFragTag() {
            return fragTag;
        }
    }


    public static class Intent extends android.content.Intent {
        public Intent(Context packageContext) {
            super(packageContext, FragmentActivity.class);
        }
    }
}

这篇关于申请后重叠隐藏片段杀死后恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆