Android Studio中OnResume与SharedPreferences使用问题:运行时致命错误
Hey Jeff,我仔细看了你的报错日志和代码,马上就发现问题所在了——根本不是onResume的锅,而是你在类的成员变量声明阶段就直接调用了findViewById!
先看报错栈里的关键信息:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference ... at com.example.androidlabs.MainActivity.<init>(MainActivity.java:19)
这里明确指向了你初始化Button next和EditText name的那两行代码。原因很简单:Activity的生命周期是先创建实例(此时会初始化类的成员变量),之后才会执行onCreate方法加载布局。你在实例刚创建时就调用findViewById,这时候Activity的上下文还没完全初始化,布局也还没加载,自然找不到对应的控件,返回的都是null。后面不管是点击事件里用next.setOnClickListener,还是onResume里用name.setText,都会因为空指针崩溃。
修复步骤:
- 把控件声明和初始化拆分:只在类里声明控件变量,初始化操作放到
onCreate方法里,而且必须在setContentView(R.layout.main_activity)之后——因为只有加载了布局,findViewById才能找到对应的ID。 - 优化重复的控件查找:你的
openNameActivity方法里又重新查找了一次name,直接用成员变量就行,不用重复操作。
修改后的代码示例:
package com.example.androidlabs; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { // 只声明变量,不要在这里初始化! Button next; EditText name; public static final String SHARED_PREF = "sharedprefs"; // 统一键名,避免硬编码出错 public static final String KEY_NAME = "name"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); // 在这里初始化控件,布局已经加载完成了 next = findViewById(R.id.next); name = findViewById(R.id.name); next.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SharedPreferences sh = getSharedPreferences(SHARED_PREF, MODE_PRIVATE); SharedPreferences.Editor editor = sh.edit(); editor.putString(KEY_NAME, name.getText().toString()); editor.apply(); openNameActivity(); } }); } @Override protected void onResume() { super.onResume(); SharedPreferences sh = getSharedPreferences(SHARED_PREF, MODE_PRIVATE); String savedName = sh.getString(KEY_NAME, null); if (savedName != null){ name.setText(savedName); } } @Override protected void onPause() { super.onPause(); SharedPreferences sh = getSharedPreferences(SHARED_PREF, MODE_PRIVATE); SharedPreferences.Editor editor = sh.edit(); editor.putString(KEY_NAME, name.getText().toString()); editor.apply(); } public void openNameActivity(){ // 直接用成员变量name,不用重新findViewById String nameText = name.getText().toString(); Intent intent = new Intent(MainActivity.this, NameActivity.class); intent.putExtra(KEY_NAME, nameText); startActivityForResult(intent, 1); }; @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1) { if(resultCode == RESULT_OK){ int result = data.getIntExtra("namePref", 0); if(result == 0){ Toast.makeText(MainActivity.this,"Choose a new name", Toast.LENGTH_LONG).show(); }else{ finishAndRemoveTask(); } } if(resultCode == RESULT_CANCELED){ Toast.makeText(MainActivity.this,"Something went wrong", Toast.LENGTH_LONG).show(); } } } }
这样修改后,控件会在布局加载完成后正确初始化,空指针问题就解决了,你的SharedPreferences在onPause/onResume里的逻辑也能正常工作啦!
备注:内容来源于stack exchange,提问作者Jeff Jackson
相关产品推荐
相关产品推荐

