有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java共享首选项空指针异常

我正在为我的笔记Android应用程序添加共享首选项,我遇到了一个特殊的空指针异常。我目前正在我的应用程序中测试字体大小和字体的设置,并且已经成功地保存了这两种字体的共享首选项,但检索部分遇到了问题。当设置被更改时,他们成功地在应用程序打开的剩余时间内更改了片段上的字体和字体大小,但如果应用程序重新启动,我无法恢复它们

第一个奇怪的空指针在onCreate中

OnCreate:

    //create a new note fragment if one has not been created yet
    mNoteFragment = (NoteFragment) getFragmentManager().findFragmentById(R.id.container);
    if (mNoteFragment == null) {
        mNoteFragment = new NoteFragment();
        getFragmentManager().beginTransaction()
                .replace(R.id.container, mNoteFragment).commit();
    }

    //restore SharedPreferences
    SharedPreferences sharedPrefs = getPreferences(0);
    int stylePref = sharedPrefs.getInt(SharedPreferanceConstants.PREF_FONT_SIZE, 2);
    String fontPref = sharedPrefs.getString(SharedPreferanceConstants.PREF_TYPEFACE, "");
    Log.e("STYLEID", String.valueOf(stylePref));
    Log.e("FONTTYPE", fontPref);
    onStyleChange(null , stylePref); //NULL POINTER EXCEPTION HERE
    onFontChange(null, fontPref);

日志输出“3”和“Impact”,这是大小和字体的正确值,表示stylePref和fontPref不为空

下一个空指针如下所示:

    @Override
    public void onStyleChange(CustomStyleDialogFragment dialog, int styleId) {
        Log.d("NOTEFRAGMENT", String.valueOf(mNoteFragment));
        mNoteFragment.setCustomStyle(styleId); //NULL POINTER EXCEPTION HERE
    }

    @Override
    public void onFontChange(CustomStyleDialogFragment dialog, String fontName) {
        mNoteFragment.setCustomFont(fontName);
    }

我测试了styleId的值,得到了“3”,所以这似乎不是问题所在。根据日志,mNoteFragment也不为null

这是NoteFragment中的第三个NP异常。JAVA这就是我最终将EditText视图设置为所需设置的地方。我在没有共享首选项的情况下更改字体和大小没有问题,所以我不确定这里的问题

    public void setCustomFont(String fontName) {
        if(fontName.equals("Helvetica")) {
            mEditText.setTypeface(mHelvetica);
        }
        else if(fontName.equals("Helvetica-Neue")) {
            mEditText.setTypeface(mHelveticaNeue);
        }
        else if(fontName.equals("Impact")) {
            mEditText.setTypeface(mImpact);
        }
        else {
            mEditText.setTypeface(Typeface.DEFAULT);
        }
    }

    public void setCustomStyle(int styleId) {
        if(styleId == 1) {
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Small);
        }
        else if(styleId == 2) {
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Medium);
        }
        else if(styleId == 3) {
            //NULL POINTER EXCEPTION HERE
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Large);
        }
}

当然,这里是logcat。提前谢谢

11-18 10:31:53.030  18966-18966/com.richluick.blocnotes I/Process﹕ Sending signal. PID: 18966 SIG: 9
11-18 10:35:32.838  19248-19248/com.richluick.blocnotes D/STYLEID﹕ 3
11-18 10:35:32.838  19248-19248/com.richluick.blocnotes D/FONTTYPE﹕ Impact
11-18 10:35:32.839  19248-19248/com.richluick.blocnotes D/ERROR﹕ NoteFragment{422972f8 id=0x7f090001}
11-18 10:35:32.840  19248-19248/com.richluick.blocnotes D/AndroidRuntime﹕ Shutting down VM
11-18 10:35:32.840  19248-19248/com.richluick.blocnotes W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x4197dd40)
11-18 10:35:32.842  19248-19248/com.richluick.blocnotes E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.richluick.blocnotes, PID: 19248
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.richluick.blocnotes/com.richluick.blocnotes.BlocNotes}: java.lang.NullPointerException
            at 安卓.app.ActivityThread.performLaunchActivity(ActivityThread.java:2198)
            at 安卓.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
            at 安卓.app.ActivityThread.access$800(ActivityThread.java:139)
            at 安卓.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
            at 安卓.os.Handler.dispatchMessage(Handler.java:102)
            at 安卓.os.Looper.loop(Looper.java:136)
            at 安卓.app.ActivityThread.main(ActivityThread.java:5097)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.安卓.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.安卓.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.richluick.blocnotes.NoteFragment.setCustomStyle(NoteFragment.java:86)
            at com.richluick.blocnotes.BlocNotes.onStyleChange(BlocNotes.java:139)
            at com.richluick.blocnotes.BlocNotes.onCreate(BlocNotes.java:61)
            at 安卓.app.Activity.performCreate(Activity.java:5248)
            at 安卓.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
            at 安卓.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
            at 安卓.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
            at 安卓.app.ActivityThread.access$800(ActivityThread.java:139)
            at 安卓.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
            at 安卓.os.Handler.dispatchMessage(Handler.java:102)
            at 安卓.os.Looper.loop(Looper.java:136)
            at 安卓.app.ActivityThread.main(ActivityThread.java:5097)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.安卓.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.安卓.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

注意片段。爪哇

public class NoteFragment extends Fragment {

    public EditText mEditText;
    private Typeface mHelvetica;
    private Typeface mHelveticaNeue;
    private Typeface mImpact;

    private static final String TEXT = "text";

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString(TEXT, mEditText.getText().toString());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_note, container, false);
        setHasOptionsMenu(true);

        //restore state of app when activity is destroyed and restarted
        mEditText = (EditText) rootView.findViewById(R.id.editText);
        if (savedInstanceState != null) {
            mEditText.setText(savedInstanceState.getString(TEXT));
        }

        //Store the font assets as variables
        mHelvetica = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Helvetica_Reg.ttf");
        mHelveticaNeue = Typeface.createFromAsset(getActivity().getAssets(), "fonts/HelveticaNeue_Lt.ttf");
        mImpact = Typeface.createFromAsset(getActivity().getAssets(), "fonts/impact.ttf");

        return rootView;
    }

    /**
     * This is a setter method for setting the font the user has selected from the spinner
     *
     * param fontName the name of the font the user selected
     * @return void
     * */
    public void setCustomFont(String fontName) {
        if(fontName.equals("Helvetica")) {
            mEditText.setTypeface(mHelvetica);
        }
        else if(fontName.equals("Helvetica-Neue")) {
            mEditText.setTypeface(mHelveticaNeue);
        }
        else if(fontName.equals("Impact")) {
            mEditText.setTypeface(mImpact);
        }
        else {
            mEditText.setTypeface(Typeface.DEFAULT);
        }
    }

    /**
     * This is a setter method for setting the font style the user has selected from custom menu
     *
     * param styleId the integer id of the font stlye selected (SMALL, MEDIUM, LARGE)
     * @return void
     * */
    public void setCustomStyle(int styleId) {
        if(styleId == 1) {
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Small);
        }
        else if(styleId == 2) {
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Medium);
        }
        else if(styleId == 3) {
            Log.d("EDITTEXT", String.valueOf(mEditText));
            mEditText.setTextAppearance(getActivity(), 安卓.R.style.TextAppearance_Large);
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Inflate the menu; this adds items to the action bar if it is present.
        super.onCreateOptionsMenu(menu, inflater);

        inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.bloc_notes, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_erase) {
            mEditText.setText("");
        }
        return super.onOptionsItemSelected(item);
    }
}

共 (4) 个答案

  1. # 1 楼答案

    SomeActivity.onCreate()中,您正在创建NoteFragment的实例,但即使您通过事务提交它,也不会立即膨胀和创建它。这基本上意味着NoteFragment.onCreateView()没有被执行,片段UI也没有被创建。然而,你的活动。onCreate()假设mFragment.mEditText已经设置,但事实并非如此,因此您会遇到NullPointerException

    看看FragmentTransation.commit方法:http://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#commit()

    Schedules a commit of this transaction. The commit does not happen immediately; it will 
    be scheduled as work on the main thread to be done the next time that thread is ready.
    
  2. # 2 楼答案

    尝试使用“应用”而不是“提交”,理由如下->^卢卡斯·克努特著{a1}

    但基本上,apply()会立即将其更改提交到内存中的SharedReference

    强烈建议使用类来管理您的首选项,如“MyPreferencesManager”

  3. # 3 楼答案

    好吧,我不知道为什么会这样,但我能根据这个问题找出答案:

    onCreateView() in Fragment is not called immediately, even after FragmentManager.executePendingTransactions()

    我加了一行

    getFragmentManager().executePendingTransactions();
    

    然后将所有内容转移到onStart方法

    @Override
        protected void onStart() {
            super.onStart();
    
            //create a new note fragment if one has not been created yet
            mNoteFragment = (NoteFragment) getFragmentManager().findFragmentById(R.id.container);
            if (mNoteFragment == null) {
                mNoteFragment = new NoteFragment();
                getFragmentManager().beginTransaction().replace(R.id.container, mNoteFragment).commit();
                getFragmentManager().executePendingTransactions();
            }
    
            //restore SharedPreferences
            SharedPreferences sharedPrefs = getPreferences(0);
            int stylePref = sharedPrefs.getInt(SharedPreferanceConstants.PREF_FONT_SIZE, 2);
            String fontPref = sharedPrefs.getString(SharedPreferanceConstants.PREF_TYPEFACE, "");
            Log.d("STYLEID", String.valueOf(stylePref));
            Log.d("FONTTYPE", fontPref);
            onStyleChange(null , stylePref);
            onFontChange(null, fontPref);
        }
    

    出于某种原因,它现在运行良好。如果有人能解释为什么那很好

  4. # 4 楼答案

    此时NoteFragment中的mEditText为空,因此NPE为空

    只需在片段的onCreate()或onActivityCreated()中初始化成员mEditText,而不是onCreateView()。这将确保在调用setter时mEditText不为null

    无论发生什么情况,都应该防止setter函数中出现null mEditText

    编辑这就是我的意思:

    public void setCustomFont(String fontName) {
          if(mEditText != null){
            if(fontName.equals("Helvetica")) {
                mEditText.setTypeface(mHelvetica);
            }
            else if(fontName.equals("Helvetica-Neue")) {
                mEditText.setTypeface(mHelveticaNeue);
            }
            else if(fontName.equals("Impact")) {
                mEditText.setTypeface(mImpact);
            }
            else {
                mEditText.setTypeface(Typeface.DEFAULT);
            }
            }
        }
    

    编辑2:Oncreate不是一个好地方。基本上,您希望在fragmentmanager提交更改后调用setter,以便mEditText已初始化

    编辑3-用你的初始代码试试这个:

        getFragmentManager().beginTransaction().replace(R.id.container, mNoteFragment).commit();
        getFragmentManager().executePendingTransactions();