【问题标题】:Fragment replacing returns NullPointerException片段替换返回 NullPointerException
【发布时间】:2015-04-10 07:35:49
【问题描述】:

关于这个主题有很多主题,但我找不到任何对我的案例有帮助的解决方案。

背后的想法:

我有一个 ViewPager,用于在 3 个片段之间切换。这样可行。但是在提到的片段之一中,我做了一些功能 - 然后我检查了之前提到的片段中的另一个。一切正常。 然后,当我进行检查时,我打开一个 AlertDialog,告诉用户他的配置是成功的。通过单击按钮,我希望该应用程序将用户转移到一个不同的片段(不是 ViewPager 片段之一)。

代码片段 - FragmentTwo:

public void displayAlertSuccess(Context ctx) {
        new AlertDialog.Builder(ctx)
                .setTitle("ACCESS GRANTED!")
                .setMessage("Congratulations!")
                .setPositiveButton("Great!", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // continue with
                            replaceFragment();
                    }

                })
                .setNegativeButton("Format my Card", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        mainActivity.setNFC_ACTION("FORMAT");

                    }
                })
                .setIcon(android.R.drawable.ic_dialog_info)
                .show();
    }

    private void replaceFragment() {


        Fragment frag = new CardDesfire1();
        getFragmentManager().beginTransaction().replace(R.id.content_frame, frag).commit();


    }

代码片段 - XML 布局:

我。 activity_holder.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- As the main content view, the view below consumes the entire
     space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</LinearLayout>

二。 activity_access.xml

<!-- activity_screen_slide.xml -->
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

三。 fragment_access_slide2.xml(有对话框的片段)

<!-- fragment_screen_slide_page.xml -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff0080ff">


    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:id="@+id/imageButton"
        android:src="@drawable/img_access_slide2_2"/>
</ScrollView>

四。 activity_desfire1.xml(我想在点击时启动的片段)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:background="@drawable/bg_des2">

    <Button
        android:layout_width="fill_parent"
        android:layout_height="25dp"
        android:text="You have discovered..."
        android:id="@+id/btn_des1_discovered"
        android:background="#3A5FCD"
        android:typeface="monospace"
        android:textColor="#ffffffff"
        android:enabled="false"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <Button
        android:id="@+id/btn_loy"
        android:text="Loyalty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/buttons_shape"
        android:shadowColor="#000000"
        android:textColor="#FFFFFF"
        android:shadowDx="0"
        android:shadowDy="0"
        android:shadowRadius="5"
        android:layout_above="@+id/btn_pay"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:textAllCaps="false"
        android:visibility="invisible"/>
    <Button
        android:id="@+id/btn_pay"
        android:text="&#181;Pay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/buttons_shape"
        android:shadowColor="#000000"
        android:textColor="#FFFFFF"
        android:shadowDx="0"
        android:shadowDy="0"
        android:shadowRadius="5"
        android:textAllCaps="false"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="70dp"
        android:layout_centerHorizontal="true"
        android:visibility="invisible"/>
    <Button
        android:id="@+id/btn_acc"
        android:text="Access"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/buttons_shape"
        android:shadowColor="#000000"
        android:textColor="#FFFFFF"
        android:shadowDx="0"
        android:shadowDy="0"
        android:shadowRadius="5"
        android:textAllCaps="false"
        android:layout_above="@+id/btn_pay"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:visibility="invisible"/>
    <ImageView
        android:layout_width="wrap_content"
        android:visibility="invisible"
        android:layout_height="wrap_content"
        android:id="@+id/img_card_des1"
        android:layout_below="@+id/btn_des1_discovered"
        android:src="@drawable/img_card_des1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="48dp" />


    <TextView
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:visibility="invisible"
        android:textSize="18dp"
        android:gravity="center"
        android:text="@string/des1_desc"
        android:id="@+id/tv_des1_desc"
        android:textColor="#ffffffff"
        android:textStyle="italic"
        android:background="#ff8db6cd"
        android:layout_below="@+id/img_card_des1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="40dp" />

</RelativeLayout>

错误线:

getFragmentManager().beginTransaction().replace(R.id.content_frame, frag).commit();

来自 LogCat 的错误描述:

java.lang.NullPointerException

在以下情况下发生错误:

当用户单击 AlertDialog 中的“Great”按钮时出现我的错误,然后应该调用 Fragment 替换。

我试过了:

我尝试使用 getChildFragment 修复它,但随后出现不同类型的错误:IllegalStateException : Activity has been destroyed

非常感谢任何帮助。

【问题讨论】:

  • R.id.content_frame 是否正确,您检查了吗?
  • 请添加所有相关信息,例如 R.id.content_frame 是什么(显示布局 XML),异常的完整堆栈跟踪。据我所知:试试getActivity.getFragmentManager()
  • @Kesh1234 是的,这是正确的。 dhke 我的错误,忘记发布 XML 的。就可以了,会更新的。 getActivity 没有帮助。
  • 您是否尝试分解该失败的复合语句以准确识别空值?
  • @sudocode 不,我还没有,我对调试不是很好,所以我先在这里发布。但如果不出意外,我将不得不一步一步调试它。

标签: java android android-fragments android-viewpager android-nested-fragment


【解决方案1】:

您是否在 CardDesfire1 片段中声明了默认构造函数。如果没有,则声明它

public CardDesfire1(){}

让你的父 Activity 扩展 FragmentActivity

class ParentActivity extends FragmentActivity

【讨论】:

  • 嘿 Vikalp,我尝试添加构造函数,但在同一行代码中仍然出现相同的错误(空指针)。
  • 现在,我认为你应该调试你的代码并检查什么是空的。我的意思是检查哪个方法( getFragmentManager() OR beginTransaction() OR replace(R.id.content_frame, frag) OR commit() )返回null。
  • 感谢您的回复。我同时检查了它,并且我已经在 getFragmentManager() 处得到了 nullpointed。但是,我已经尝试过 getActivity.getSupportFragmentManager() 和 getChildFragmentManager(),都没有解决问题。
  • 如果 Fragment 的父 Activity 扩展了 Activity 则改为扩展 FragmentActivity。
  • 是的,我的父活动是 MainActivity,它确实扩展了 FragmentActivity。嗯,不知道这里发生了什么..
【解决方案2】:

出现问题是因为您在 Fragment 中调用 getFragmentManager(),您应该将显示对话框委托给 Activity。

使活动实现一个接口,并让片段在显示对话框时调用此接口方法。

示例:您在 FragmentTwo 中定义了一个新的内部接口(此代码在 FragmentTwo 中):

public interface OnReplaceFragmentListener {
    void onReplaceFragment();
}

您将您的活动链接到片段(此代码在 FragmentTwo 中):

private OnReplaceFragmentListener mCallback;

 @Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        mCallback = (OnReplaceFragmentListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnReplaceFragmentListener");
    }
}

private void replaceFragment() {
    mCallback.onReplaceFragment();
}

然后让activity实现OnReplaceFragmentListener。 并且(此代码进入 FragmentTwo 的托管活动):

@Override
void onReplaceFragment() {
    Fragment frag = new CardDesfire1();
    getFragmentManager().beginTransaction().replace(R.id.content_frame, frag).commit();
}

【讨论】:

  • 您能否发布一个简短的示例,说明您如何在我的情况下实现此类接口?
  • 添加相关示例
  • 测试。很快就会公布结果。
  • 仍然错误:NullPointerException: mCallback.onReplaceFragment();在 AccessSlideTwo 片段内。
  • 回调应该在片段中,对吧?不在活动中?我把它放在 Fragment 类中。
猜你喜欢
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
  • 2012-01-07
  • 2019-07-11
相关资源
最近更新 更多