[英]Android NullPointerException for findViewById on spinner
我有一个 android 应用程序,它已在 Google Play 商店发布了一段时间。 它对 99.9% 的用户运行良好。 但是,Google Play 控制台告诉我,一些用户正在遭受由活动的 onCreate 例程中的 NullPointerException 引起的崩溃。 有问题的特定行是:
final Spinner choose_music = findViewById(R.id.music_list);
该例程似乎永远不会因例程中对findViewById
的任何其他调用而崩溃,只是微调器的调用(而且很少)。 下面列出了我的布局文件,尽管我怀疑它是否相关。 恐怕我没有任何 logcat output,因为 Play 控制台不提供。
当该活动启动时,从活动内调用onCreate
例程。 我在下面包含了完整的onCreate
例程,但微调器的发现还很早。
有任何想法吗? 谢谢
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@color/light_grey"
tools:context=".PlayActivity" >
<RelativeLayout
android:id="@+id/main_canvas"
android:layout_weight="90"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/colorAccent">
</RelativeLayout>
<RelativeLayout
android:id="@+id/bottom_panel"
android:layout_weight="90"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/layout_choose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/layout_volume"
android:layout_alignBottom="@id/layout_volume"
android:background="@color/mid_grey"
android:layout_alignParentLeft="true">
<TextView
android:id="@+id/choose_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Music"
android:padding="5sp"
android:textSize="20sp"/>
<Spinner
android:id="@+id/music_list"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_below="@id/choose_music"
android:layout_height="wrap_content"></Spinner>
</RelativeLayout>
<TextView
android:id="@+id/padding_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/layout_choose"
android:text="."
android:textColor="@color/light_grey"
android:padding="2sp"
android:textSize="20sp"/>
<RelativeLayout
android:id="@+id/layout_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/mid_grey"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/padding_text">
<TextView
android:id="@+id/choose_volume"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:text="Relative volume"
android:padding="0sp"
android:textSize="20sp"/>
<TextView
android:id="@+id/volume_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/choose_volume"
android:layout_alignParentLeft="true"
android:text="Music"
android:padding="5sp"
android:textSize="20sp"/>
<TextView
android:id="@+id/volume_speech"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/choose_volume"
android:layout_alignParentRight="true"
android:text="Speech"
android:padding="5sp"
android:textSize="20sp"/>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/relative_volume"
android:padding="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/volume_speech"/>
</RelativeLayout>
</RelativeLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
my_view = (RelativeLayout) findViewById(R.id.main_canvas);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
view = new CircularMusicController(PlayActivity.this, height, width);
my_view.addView(view, new ActionBar.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
globals.crash_log("Layout dimensions before: " + String.valueOf(my_view.getWidth() + ", "
+ String.valueOf(my_view.getHeight())));
my_view.setLayoutParams(new LinearLayout.LayoutParams(view.get_width(), view.get_height()));
// Get ListView object from xml
final Spinner choose_music = findViewById(R.id.music_list);
int music_index = 0;
for (int i=0; i<globals.music_track_list.length; i+=1) {
if (globals.appState.get_music().equals(globals.music_track_list[i])) {
music_index = i;
}
}
chosen_music = music_index;
// ListView Item Click Listener
ArrayAdapter<CharSequence> music_adapter = new ArrayAdapter<CharSequence>(this, R.layout.activity_listview, globals.music_names);
choose_music.setAdapter(music_adapter);
choose_music.setSelection(music_index);
choose_music.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
globals.crash_log("I have chosen " + String.valueOf(i));
if (chosen_music > 0 && musicBound && musicSrv != null) {
musicSrv.halt();
}
chosen_music = i;
if (musicBound) {
if (i > 0) {
musicSrv.setSong(globals.music_locs[i]);
if (isPlaying()) {
musicSrv.playSong(isPlaying());
} else {
choice_while_paused = true;
}
}
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
globals.crash_log("Layout dimensions: " + String.valueOf(my_view.getWidth() + ", "
+ String.valueOf(my_view.getHeight())));
volume_control = findViewById(R.id.relative_volume);
volume_control.setProgress(globals.appState.get_volume());
volume_control.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int volume, boolean from_user) {
if (from_user) {
int focus_vol = globals.roc_function(volume);
try {
if (speechSrv != null) {
speechSrv.set_volume(focus_vol);
}
if (musicSrv != null) {
musicSrv.set_volume(100 - focus_vol);
}
} catch (Exception err) {
globals.crash_log("Failed to set volume");
globals.crash_exception(err);
}
}
globals.crash_log("SeekBar: new volume is " + String.valueOf(volume) + " " +
String.valueOf(from_user));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Get any information passed down from the parent activity
Intent intent = getIntent();
track_name = intent.getStringExtra("name");
track_location = intent.getStringExtra("location");
res_location = intent.getIntExtra("res_location", 0);
activity_name = intent.getStringExtra("activity_name");
globals.crash_log("PlayActivity: onCreate: activity_name is " + activity_name);
globals.crash_log("PlayActivity: onCreate: track_name is " + track_name);
if ( ! (track_location == null) ) {
globals.crash_log("PlayActivity: onCreate: track_loc is " + track_location);
}
globals.crash_log("PlayActivity: onCreate: res_location is "+String.valueOf(res_location));
// Setup the action bar, and start the broadcast receiver.
ActionBar action_bar = getSupportActionBar();
action_bar.setTitle(track_name);
action_bar.setDisplayHomeAsUpEnabled(true);
IntentFilter filter = new IntentFilter("PLAY_ACTIVITY");
this.registerReceiver(_refreshReceiver, filter);
}
onCreate() 是您要膨胀视图和/或初始化其他对象的地方。 我建议这样做:
替代解决方案,使用 DataBinding,因为它是 null 安全的。
在那条线上使用 NPE 崩溃是没有意义的。 如果findViewById()
在 NPE-worthy state 中(就像在活动附加到Window
之前调用该方法),它上面会有 NPE 已经有很多行。
我怀疑行号报告略微偏离(它发生了),实际上是您的globals.music_track_list
在某些情况下是null
,并且尝试读取它的length
是这里的 NPE。
我还鼓励您使用比 Play 控制台更通用的崩溃报告服务。 例如,Crashlytics。 Play 控制台的问题之一是未报告异常消息和嵌套异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.