我正在努力将共享首选项添加到我的笔记本中使用Android应用程序,我遇到了一个特殊的空指针异常。我目前正在我的应用程序中测试字体大小和字体的设置,并且能够成功保存两者的共享首选项,但是我在检索部分遇到问题。更改设置后,他们会在应用程序打开的剩余时间内成功更改Fragment上的字体和字体大小,但如果重新启动应用程序,则无法恢复它们。
第一个奇怪的Null Pointer在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"和"影响"这是size和font的正确值,表示stylePref和fontPref不为null。
下一个空指针在下面。:
@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根据日志不为空。
这是NoteFragment.java中的第三个NP Exception。这是我最终将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(), android.R.style.TextAppearance_Small);
}
else if(styleId == 2) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Medium);
}
else if(styleId == 3) {
//NULL POINTER EXCEPTION HERE
mEditText.setTextAppearance(getActivity(), android.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 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2198)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.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.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.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 android.app.Activity.performCreate(Activity.java:5248)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.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.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
NoteFragment.java
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(), android.R.style.TextAppearance_Small);
}
else if(styleId == 2) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Medium);
}
else if(styleId == 3) {
Log.d("EDITTEXT", String.valueOf(mEditText));
mEditText.setTextAppearance(getActivity(), android.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);
}
}
答案 0 :(得分:1)
此时,NoteFragment中的mEditText为null,因此为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();
答案 1 :(得分:1)
在您的SomeActivity.onCreate()
中,您正在创建NoteFragment
的实例,但即使您通过交易提交,也不会立即对其进行充气和创建。这基本上意味着,NoteFragment.onCreateView()
没有执行,片段UI尚未创建。但是,您的Activity.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 :(得分:0)
好的所以我不确定为什么会这样,但我能够根据这个问题找出答案:
我添加了以下行
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);
}
由于某种原因,它现在工作正常。如果有人能解释为什么那会很棒
答案 3 :(得分:-1)
尝试使用'申请'而不是提交' ,理由就在这里 - > Lukas Knuth What's the difference between commit() and apply() in Shared Preference。
但基本上,apply()会立即将其更改提交到内存中的SharedPreferences。
强烈建议您使用课程来管理您的偏好,例如“MyPreferencesManager”。