首页 > 解决方案 > 片段组件在方向更改时为空

问题描述

我的游戏配置文件活动收到带有传入 id 的意图,然后我使用该 id 从我的 firebase 数据库请求具有该 id 的游戏,并且只有当找到游戏时,我才会在片段中设置其信息。

这是我请求然后将 _Game 对象添加到我的片段的方式(为简洁起见省略了代码,通常我添加了所有 ChildEventListener 方法)

    public void findGameById(final int id) {
    mGamesRef.orderByChild("id")
            .equalTo(id)
            .limitToFirst(1)
            .addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    _Game game = dataSnapshot.getValue(_Game.class);
                    mGameInfoFragment.setGameInfo(game);
                }
            });
}

当然,作为参数传递的 id 是从意图中获得的 id。findGameById(int id)在活动的 OnCreate 中调用

GameInfoFragmentsetGameInfo(_Game game)哪里

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_game_info, container, false);
    String dateFormat = SharedPrefManager.read(SharedPrefManager.KEY_PREF_REGION, getString(R.string.default_date_format));
    mDateFormatter = new SimpleDateFormat(dateFormat);
    mTodayTimeMillis = Calendar.getInstance().getTimeInMillis();
    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // Summary UI
    mTextSummary = view.findViewById(R.id.summary);
    mReadMore = view.findViewById(R.id.read_more);
    mSummaryLoading = view.findViewById(R.id.summary_loading);
}

    public void setGameInfo(_Game game) {
    // Stop/hide all ongoing progress bars (loading)
    mSummaryLoading.setVisibility(View.GONE);

}

在我改变方向之前一切都很好,因为在改变方向时它会给我以下错误:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.widget.ProgressBar.setVisibility(int)”

标签: androidandroid-fragments

解决方案


默认情况下,Android 框架会在配置更改时销毁片段并重新创建它。如果您没有自己处理配置更改,那么您的片段已被重新创建。这个对片段的引用

mGameInfoFragment.setGameInfo(game);

可能不再有效,因此出现 NullPointerException。根据经验,不要存储对具有生命周期的对象的引用,例如活动和片段,因为它们是易失性的并且可能导致内存泄漏(您的就是内存泄漏的一个例子,系统无法释放您的旧片段,因为您仍然有一个参考它)。

一种方法是自己处理方向变化。在这里进一步阅读

android:configChanges="orientation"

另一种方法是确保在调用方法之前始终获得框架膨胀和显示的片段。


推荐阅读