【问题标题】:App is crashing after saving value to Shared Preferences将值保存到共享首选项后应用程序崩溃
【发布时间】:2020-06-20 21:07:58
【问题描述】:

我正在尝试使用 Android Studio(使用 java)编写我的第一个应用程序,但我被卡住了。 应用程序应该从用户那里获取输入(使用纯文本),然后保留它并在下次启动应用程序时显示它。 我希望能够在应用程序启动之间保留数据,据我了解,最有效和最优雅的方式是使用共享首选项。但是每次我按下将文本保存到共享首选项的按钮时,应用程序都会崩溃。

这是我的代码:

public class FirstFragment extends Fragment {
    
    private final String PREFS = "sharedPrefs";
    private final String INPUT = "user_input";
    private final String MEMO = "memo";
    SharedPreferences sharedPreferences = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);

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

    private void saveData(View view) {
        TextView input = view.findViewById(R.id.user_input);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(MEMO, input.getText().toString());
        editor.apply();
    }

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        sharedPreferences = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);

        TextView memos = view.findViewById(R.id.memos);
        memos.setText(sharedPreferences.getString(MEMO, ""));

        view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                saveData(view);
            }
        });
    }

编辑:我的崩溃日志:

 进程:com.example.myfirstapplication,PID:2322
    java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“java.lang.CharSequence android.widget.TextView.getText()”
        在 com.example.myfirstapplication.FirstFragment.saveData(FirstFragment.java:32)
        在 com.example.myfirstapplication.FirstFragment.access$000(FirstFragment.java:14)
        在 com.example.myfirstapplication.FirstFragment$1.onClick(FirstFragment.java:47)
        在 android.view.View.performClick(View.java:7161)
        在 android.view.View.performClickInternal(View.java:7138)
        在 android.view.View.access$3500(View.java:811)
        在 android.view.View$PerformClick.run(View.java:27419)
        在 android.os.Handler.handleCallback(Handler.java:883)
        在 android.os.Handler.dispatchMessage(Handler.java:100)
        在 android.os.Looper.loop(Looper.java:224)
        在 android.app.ActivityThread.main(ActivityThread.java:7520)
        在 java.lang.reflect.Method.invoke(本机方法)
        在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

很高兴看到是否有人可以解决我的问题!

【问题讨论】:

  • 请添加您的崩溃日志

标签: android android-fragments sharedpreferences


【解决方案1】:

当你按下按钮时,你调用 saveData() 方法。但是您将按钮视图设置为参数而不是根视图。你应该这样做

view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) { 
        // change onClick's parameter name from view to v
            saveData(view);
        }
    });

【讨论】:

  • 它不允许我使用外部范围的视图,因为它是从内部类中访问的,它应该被声明为 final。
【解决方案2】:

SharedPrefrence 对象的赋值添加为Fragment 字段肯定会引发异常,因为它在片段附加到您的活动之前被调用,并且就fragment lifecycle 而言,onAttach() 回调尚未调用,因此,getActivity() 将为 null。

SharedPreferences sharedPreferences = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);

你会得到的例外是这样的:

java.lang.IllegalStateException: Fragment FirstFragment{cfb327} (a42392bd-ee02-48a2-9d61-aaa8c455bb10)} not attached to an activity.

要解决这个问题,请替换以下行

SharedPreferences sharedPreferences = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);

SharedPreferences sharedPreferences;

而且你已经在onViewCreated() 方法中初始化了它。

【讨论】:

  • 我还是崩溃了,错误是:java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference
【解决方案3】:

使用调试器可以看到,在saveData 函数中,input 变量仍然是Null。为了解决这个问题,替换:

TextView input = view.findViewById(R.id.user_input);

与:

TextView input = getActivity().findViewById(R.id.user_input);

您可以检查input 的值来验证所需的字符串确实存在。

附言现在在您的函数中使用view 参数是多余的,应该删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 2012-11-14
    相关资源
    最近更新 更多