关于片段娱乐的NPE。片段

时间:2016-08-31 21:33:03

标签: java android android-fragments

我已经阅读了与此问题相关的所有其他主题,似乎没有人帮我解决问题。

我正在asynctask中执行一些后台任务,需要持续进行方向更改(configChanges)。我已经通过使用片段和setRetainInstance(true)得到了数据,我相信,但我的按钮(我假设任何视图真的)在方向更改时重新创建片段时被设置为null。当我在方向发生变化(重新创建片段)后尝试操作按钮引用时,这会导致空指针错误。

我试过包装按钮并调用语句中的按钮来检查包是否为空。这会停止崩溃,但不允许在重新创建片段时再次使用该按钮。

以下类扩展了Fragment。

@Override
public void onCreate(Bundle savedInstanceState) {
    if (DEBUG) Log.d(TAG, "onCreate()");
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    currentActivity = super.getActivity();

}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    if (DEBUG) Log.d(TAG, "onActivityCreated(Bundle)");
    super.onActivityCreated(savedInstanceState);

    simpleForecastIntent = new Intent(currentActivity, SimpleForecastActivity.class);

    Button fetchDataButton = (Button) currentActivity.findViewById(R.id.fetchDataButton);

    if (savedInstanceState == null) {
        fetchDataButton.setOnClickListener(fetchDataButtonListener);
        fetchDataButton.setTransformationMethod(null);
    }

    locationManager = (LocationManager)
            currentActivity.getSystemService(Context.LOCATION_SERVICE);

    if (isTaskRunning) {
        progressDialog = ProgressDialog.show(currentActivity, "Fetching data", "Please wait...");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if (DEBUG) Log.d(TAG, "onCreateView(LayoutInflater, ViewGroup,  Bundle)");

    return inflater.inflate(R.layout.main_menu, container, false);
}

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activities.MainActivity">

    <include layout="@layout/toolbar" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">

        <Button
            android:id="@+id/fetchDataButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/locationField"
            android:text="@string/fetch_weather_data"
            android:layout_centerHorizontal="true" />

        <EditText
            android:id="@+id/locationField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="@string/enter_location"
            android:layout_alignEnd="@+id/fetchDataButton"
            android:layout_alignLeft="@+id/fetchDataButton"
            android:layout_alignRight="@+id/fetchDataButton"
            android:layout_alignStart="@+id/fetchDataButton"
            android:inputType="textPostalAddress" />

        <ListView
            android:id="@+id/previousLocationsList"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/fetchDataButton"
            android:layout_centerHorizontal="true" />
    </RelativeLayout>

</LinearLayout>

我花了太多时间在一些如此微不足道的事情上,确实需要朝着正确的方向前进。如何在重新创建片段时让按钮不为空?

编辑已解决: 我正在使用处理活动的上下文来查找按钮的视图。而不是新活动视图上下文。

@Override
    public void onCreate(Bundle savedInstanceState) {
        if (DEBUG) Log.d(TAG, "onCreate()");
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        currentActivity = super.getActivity();

    }

1 个答案:

答案 0 :(得分:1)

问题是您在onActivityCreated而不是onCreateView中引用了按钮。在方向更改时,视图会被拆除然后重新创建。您应该覆盖onCreateView并从那里维护对按钮的引用。

更新:

我看到你的代码是如何工作的,但在我看来,它遵循一个糟糕的设计模式。您仍然在onActivityCreated中实例化您的视图引用,而不是在onCreateView中膨胀之后立即实例化。

我会把它切换成这样的东西:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if (DEBUG) Log.d(TAG, "onCreateView(LayoutInflater, ViewGroup,  Bundle)");

    View root = inflater.inflate(R.layout.main_menu, container, false);

    Button fetchDataButton = (Button) root.findViewById(R.id.fetchDataButton);
    ...

    return root;
}