Поддержка Android v14 PreferenceFragment аварийно завершает работу

Я пытаюсь отобразить настройки в приложении для Android, используя PreferenceFragment из библиотеки android.support.v14.preference. Однако, когда я пытаюсь открыть настройки, приложение вылетает со странным исключением NullPointerException. Этого не произойдет, если я пропущу вызов addPreferenceFromResource(R.xml.preferences) в моем PreferenceFragment, но тогда, конечно, настройки никогда не будут показаны.

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hardboard.preferencetest/com.hardboard.preferencetest.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
            at android.app.ActivityThread.access$800(ActivityThread.java:156)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:211)
            at android.app.ActivityThread.main(ActivityThread.java:5373)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
            at android.support.v14.preference.PreferenceFragment.bindPreferences(PreferenceFragment.java:473)
            at android.support.v14.preference.PreferenceFragment.onActivityCreated(PreferenceFragment.java:278)
            at android.app.Fragment.performActivityCreated(Fragment.java:2061)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:912)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.run(BackStackRecord.java:834)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
            at android.app.Activity.performStart(Activity.java:6005)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2342)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
            at android.app.ActivityThread.access$800(ActivityThread.java:156)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:211)
            at android.app.ActivityThread.main(ActivityThread.java:5373)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)

Я читал, что PreferenceFragment support-v14 использует RecyclerView внутри для отображения списка предпочтений, но что я делаю неправильно, чтобы RecyclerView был null?

Моя основная деятельность:

public class MainActivity extends AppCompatActivity implements SettingsFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .addToBackStack(null)
                .commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onFragmentInteraction(Uri uri) {

    }
}

Фрагмент предпочтения:

public class SettingsFragment extends android.support.v14.preference.PreferenceFragment {

    private OnFragmentInteractionListener mListener;

    public SettingsFragment() {
        // Required empty public constructor
    }

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

    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_settings, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        public void onFragmentInteraction(Uri uri);
    }

}

comment
пожалуйста, опубликуйте xml для fragment_settings   -  person Mohammad Tauqir    schedule 20.09.2015


Ответы (2)


PreferenceFragment уже раздувает подходящий макет для использования - используя ваш собственный R.layout.fragment_settings, он не может найти подходящие представления, которые ему требуются.

Если вы хотите изменить сам RecyclerView, рассмотрите возможность переопределения onCreateRecyclerView(). Если вместо этого вы хотите создать пользовательское обрамление вокруг макета по умолчанию, вы можете использовать такой шаблон, как:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_settings, container, false);
    // The frame you want to embed the parent layout in.
    final ViewGroup innerContainer = (ViewGroup) view.findViewById(R.id.main_frame);
    final View innerView = super.onCreateView(inflater, innerContainer, savedInstanceState);
    if (innerView != null) {
        innerContainer.addView(innerView);
    }
    return view;
}
person ianhanniballake    schedule 20.09.2015

Закомментируйте свой метод onCreateView().

Или привяжите к реализации суперкласса onCreateView() и вставьте его ответ в свою собственную оболочку, если по какой-то причине вам нужны дополнительные вещи вокруг стандартного пользовательского интерфейса PreferenceFragment.

PreferenceFragment, вероятно, ожидает, что его onCreateView() создаст RecyclerView, которого нет в вашей трассировке стека.

person CommonsWare    schedule 20.09.2015