android support v14 PreferenceFragment crashes

六月ゝ 毕业季﹏ 提交于 2019-11-30 17:40:44

问题


I'm trying to display settings in an Android app using a PreferenceFragment from the android.support.v14.preference library. However, when I try to open the preferences the app crashes with a strange NullPointerException. This doesn't happen if I leave out the call to addPreferenceFromResource(R.xml.preferences) in my the PreferenceFragment, but then of course the preferences never get shown.

 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)

I've read that the support-v14 PreferenceFragment uses a RecyclerView internally to display the list of preferences, but what am I doing wrong to result in the RecyclerView being null?

My main Activity:

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) {

    }
}

The PreferenceFragment:

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);
    }

}

回答1:


A PreferenceFragment already inflates the appropriate layout for use - by using your own R.layout.fragment_settings, it isn't able to find the appropriate views it requires.

If you'd like to modify the RecyclerView itself, consider overriding onCreateRecyclerView(). If instead you want to create some custom framing around the default layout, you can use a pattern such as:

@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;
}



回答2:


Comment out your onCreateView() method.

Or, chain to the superclass implementation of onCreateView() and embed its response in your own wrapper, if for some reason you want additional stuff around the stock PreferenceFragment UI.

PreferenceFragment probably is expecting its onCreateView() to create the RecyclerView that is missing per your stack trace.



来源:https://stackoverflow.com/questions/32682298/android-support-v14-preferencefragment-crashes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!