【问题标题】:BackStack Fragments blank on rotationBackStack Fragments 旋转时空白
【发布时间】:2014-06-25 14:27:53
【问题描述】:

在我的 Activity 中,当用户单击项目时,我正在加载片段并将它们添加到后台堆栈。这工作正常,后台加载良好。

不幸的是,当我旋转设备时,活动是空白的。我已经在 SO 和 Google 上尝试了所有可能的方法。

我尝试自己管理导航,只需在用户单击时替换片段并将返回作为导航处理。这工作正常,但我失去了我编码的自动能力,如果堆栈大于 1,我会更改导航抽屉以显示后退箭头。

我尝试移除整个堆栈,并在设备旋转时按照用户单击的顺序添加各个片段。这效果不好。似乎删除和替换不合时宜。

我尝试使用 fragmentManager.findbytag 重新添加片段,但它会引发非法状态异常“已添加片段”。我在 SO 上找到了一个解决方案来删除过渡。工作一次然后停止。不知道为什么。

我放了一个祝酒词来检查每次更改时显示的 backstack 计数,我意识到堆栈在添加后仍然显示正确的计数,但页面仍然是空白的。它甚至需要 2 次后按才能将活动退出到上一个活动。

我放了一个断点来检查片段中是否调用了onCreateView,是的,每次手机旋转时都会调用它。

基本上,自从我放弃后,我的代码现在看起来像这样。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        mPosition = 1;

        super.onCreate(savedInstanceState);

        if(savedInstanceState != null) {
            mLastArtistFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_ARTIST);
            mLastAlbumFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_ALBUM);
            mLastSongFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_SONG);

            mLastFragmentType = savedInstanceState.getInt(SAVE_FRAGMENT_LAST_TYPE);
        }

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Load();
            }
        }, 100);
    }

    void Load() {

        findViewById(R.id.loading).setVisibility(View.GONE);

        ViewStub stub = (ViewStub) findViewById(R.id.container_stub);
        stub.setLayoutResource(R.layout.activity_music);
        stub.inflate();




    if(mLastArtistFragmentTag == null) {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)


                   .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                    .commit();
        }
            else {
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)
                    //.add(R.id.base_container, Albums.newInstance(mLastArtistFragmentTag), mLastArtistFragmentTag)
//.add(R.id.base_container, getSupportFragmentManager().findFragmentByTag(mLastArtistFragmentTag), mLastArtistFragmentTag)
                    //.addToBackStack(mLastArtistFragmentTag)
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .commit();
        }

    }

@Override
    public void onSaveInstanceState(Bundle instanceState) {
        super.onSaveInstanceState(instanceState);

        if(mLastFragmentType != -1) {
            instanceState.putString(SAVE_FRAGMENT_LAST_ARTIST, mLastArtistFragmentTag);
            instanceState.putString(SAVE_FRAGMENT_LAST_ALBUM, mLastAlbumFragmentTag);
            instanceState.putString(SAVE_FRAGMENT_LAST_SONG, mLastSongFragmentTag);

            instanceState.putInt(SAVE_FRAGMENT_LAST_TYPE, mLastFragmentType);
        }

    }

片段代码是这样的

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);

    final ListView listView = (ListView) inflater.inflate(R.layout.fragment_albums, container, false);
    listView.addHeaderView(inflater.inflate(R.layout.header_artist_info, null));

    try {
        String uri2 = "http://someurl";
        NetworkRequest.FetchJSON(Request.Method.GET, uri2, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray songs = response.getJSONArray("songs");
                    //HashMap<String, Song> recentSongs = new HashMap<String, Song>();
                    ArrayList<Song> latest = new ArrayList<Song>();

                    for (int i = 0; i < songs.length(); i++) {
                        Song s = new Song(songs.getJSONObject(i));
                        latest.add(s);
                    }

                    AlbumListAdapter pgiAdapter = new AlbumListAdapter(getActivity(), latest);
                    SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(pgiAdapter);

                    swingBottomInAnimationAdapter.setAbsListView(listView);
                    listView.setAdapter(swingBottomInAnimationAdapter);

                } catch (JSONException ex) {
                    Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        });
    } catch (Exception ex) {
        Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
    }

    return listView;
}

在你问之前,是的,我确实将 Load 方法移到了 onCreate 方法中。还是不行。

我真的被困在这里,需要你的帮助。请帮我。谢谢。

【问题讨论】:

  • super.saveInstanceState
  • @MLProgrammer-CiM 我有 super.onSaveInstanceState,让我试试 createView
  • @MLProgrammer-CiM 不起作用 :(
  • 这是一个起点,超级调用对于生命周期方法是强制性的。现在,根据您重新创建活动的方式,您可能需要手动处理片段状态更改。在最坏的情况下,您可能需要分离并重新附加片段以强制重新创建视图。
  • 我想我会尝试分离并重新连接以确保。

标签: android fragmentmanager


【解决方案1】:

根据您重新创建活动的方式,您可能需要手动处理片段状态更改。在最坏的情况下,您可能需要分离并重新附加片段以强制重新创建视图。

public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  transaction.detach(activeFrag).attach(activeFrag).commit();
}

并在您的 AndroidManifest.xml 上设置正确的钩子

android:configChanges="orientation|screenSize"

【讨论】:

    【解决方案2】:

    感谢@MLProgrammer-CiM,我找到了解决此问题的方法。

    if(mLastArtistFragmentTag == null) {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                .commit();
    } else {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    
        Fragment base = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_BASE);
        Fragment art = getSupportFragmentManager().findFragmentByTag(mLastArtistFragmentTag);
    
        ft.detach(base).attach(base).detach(art).attach(art).commit();
    }
    

    我想我必须对 backstack 中的所有项目执行此操作。很高兴至少它有效。终于!

    【讨论】:

    • 我最近注意到这方面的一些活动。由于片段的问题,我完全离开并建立了一个图书馆来帮助我解决这个问题。可以在github.com/frostymarvelous/Folio找到
    猜你喜欢
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    相关资源
    最近更新 更多