- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Android Vitals 报告中的 Google Play 控制台为我提供了此信息
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2955)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3030)
at android.app.ActivityThread.-wrap11 (Unknown Source)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1696)
at android.os.Handler.dispatchMessage (Handler.java:105)
at android.os.Looper.loop (Looper.java:164)
at android.app.ActivityThread.main (ActivityThread.java:6938)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:327)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)
Caused by: java.lang.NullPointerException:
at com.golendukhin.whitenoise.GridAdapter.getCount (GridAdapter.java:52)
at android.widget.GridView.setAdapter (GridView.java:243)
at com.golendukhin.whitenoise.FoldersGridActivity.onCreate (FoldersGridActivity.java:60)
at android.app.Activity.performCreate (Activity.java:7183)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2908)
据我所知,这是因为网格适配器的 getCount 方法返回空值。因此,网格适配器不起作用。因此,不会创建整个 Activity 。只有三星设备有这样的问题。
首先,我尝试创建具有相同 Android 版本、RAM 和 ARM 的相同模拟设备。模拟器工作得非常好。没有错误。
然后我添加了一些测试以确保 getCount 有效并创建了 Activity 。
@RunWith(AndroidJUnit4.class)
public class GridViewTest {
@Rule
public ActivityTestRule<FoldersGridActivity> foldersGridActivityTestRule = new ActivityTestRule<>(FoldersGridActivity.class);
@Test
public void ensureGridAdapterIsNotNull() {
FoldersGridActivity foldersGridActivity = foldersGridActivityTestRule.getActivity();
View view = foldersGridActivity.findViewById(R.id.grid_view);
GridView gridView = (GridView) view;
GridAdapter gridAdapter = (GridAdapter) gridView.getAdapter();
assertThat(gridAdapter, notNullValue());
}
@Test
public void ensureArrayAdapterInGridActivityIsNotEmpty() {
FoldersGridActivity foldersGridActivity = foldersGridActivityTestRule.getActivity();
View view = foldersGridActivity.findViewById(R.id.grid_view);
GridView gridView = (GridView) view;
GridAdapter gridAdapter = (GridAdapter) gridView.getAdapter();
assertTrue(gridAdapter.getCount() > 0 );
}
@Test
public void gridViewIsVisibleAndClickable() {
onData(anything()).inAdapterView(withId(R.id.grid_view)).atPosition(0).perform(click());
onView(withId(R.id.toolbar_title_text_view)).check(matches(withText("rain")));
}
}
所有模拟设备再次成功通过测试。然后我添加了 FireBase TestLab 并在装有 Android 8 的 Galaxy S9 真实设备上启动了我的测试。所有测试都通过了。
适配器代码。是的,我已经覆盖了 getCount() 方法,即使它没有意义。
public class GridAdapter extends ArrayAdapter<TracksFolder> {
@BindView(R.id.folder_text_view) TextView textView;
@BindView(R.id.grid_item_image_view) ImageView imageView;
private ArrayList<TracksFolder> tracksFolders;
private Context context;
GridAdapter(Context context, int resource, ArrayList<TracksFolder> tracksFolders) {
super(context, resource, tracksFolders);
this.tracksFolders = tracksFolders;
this.context = context;
}
/**
* @return grid item, customized via TracksFolder class instance
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.grid_item, parent, false);
}
ButterKnife.bind(this, convertView);
String folderName = tracksFolders.get(position).getFolderName();
int imageResource = tracksFolders.get(position).getImageResource();
textView.setText(folderName);
imageView.setImageResource(imageResource);
return convertView;
}
/**
* Added to possibly avoid NPE on multiple devices
* Could not reproduce this error
* @return size of tracksFolders
*/
@Override
public int getCount() {
return tracksFolders.size();
}
}
所以,我有几个问题:首先,此崩溃报告是否意味着每次 Sumsung 所有者启动应用程序时都会发生此崩溃?由于一些三星设备坚持统计,我假设没有。其次,我应该怎么做才能以某种方式重现此错误并最终修复错误。
我知道问题太宽泛了,但我真的很感激任何帮助,因为我绝对不知道下一步该做什么。
入门级。使用适配器
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import com.google.firebase.crash.FirebaseCrash;
import java.util.ArrayList;
import butterknife.BindArray;
import butterknife.BindView;
import butterknife.ButterKnife;
import static com.golendukhin.whitenoise.SharedPreferencesUtils.writeToSharedPreferences;
public class FoldersGridActivity extends AppCompatActivity {
@BindView(R.id.grid_view) GridView gridView;
@BindArray(R.array.labels) String[] foldersName;
@BindView(R.id.toolbar_like_button) Button toolbarLikeButton;
@BindView(R.id.toolbar_back_button) Button toolbarBackButton;
private ArrayList<TracksFolder> tracksFolders;
/**
* Binds all UI views
* Defines variables to feed adapter and listeners
* Initializes grid adapter, sets number of columns via phone in portrait or landscape orientation
* Sets onclick listener for every grid item
* Sets onclick for toolbar "like" button
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.folders_grid_view);
ButterKnife.bind(this);
if (getIntent().getExtras() != null) { //activity is triggered via on back pressed
Bundle bundle = getIntent().getExtras();
tracksFolders = (ArrayList<TracksFolder>) bundle.getSerializable("tracksFolders");
} else if (savedInstanceState != null) { //this happens after screen is rotated
tracksFolders = (ArrayList<TracksFolder>) savedInstanceState.getSerializable("tracksFolders");
} else { //this happens if app is launched by user
tracksFolders = getTracksFolders();
initService();
}
toolbarBackButton.setVisibility(View.GONE);
GridAdapter gridAdapter;
gridAdapter = new GridAdapter(this, R.id.grid_view, tracksFolders);
gridView.setNumColumns(getResources().getInteger(R.integer.columns_number));
gridView.setAdapter(gridAdapter);
FirebaseCrash.log("Activity created");
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Bundle bundle = new Bundle();
bundle.putSerializable("tracksFolders", tracksFolders);
bundle.putInt("folderPosition", position);
Intent intent = new Intent(FoldersGridActivity.this, TracksListActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
});
toolbarLikeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putSerializable("tracksFolders", tracksFolders);
bundle.putInt("activityFrom", Constants.FROM_FOLDERS_GRID_ACTIVITY);
Intent intent = new Intent(FoldersGridActivity.this, LikedTracksListActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
});
}
/**
* Saves tracksFolders array list to rebuild activity after rotation
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putSerializable("tracksFolders", tracksFolders);
writeToSharedPreferences(this, tracksFolders);
super.onSaveInstanceState(outState);
}
@Override
public void onBackPressed() {
super.onBackPressed();
moveTaskToBack(true);
}
/**
* After app is launched need to initialize audio player service
*/
private void initService() {
Intent intent = new Intent(FoldersGridActivity.this, AudioPlayerService.class);
startService(intent);
}
/**
* If tracksFolders is not stored in shared preferences, it is initialized from resources.
* @return arrayList of folders with arrayList of tracks belonging to every folder
*/
private ArrayList<TracksFolder> getTracksFolders() {
Resources resources = getResources();
TypedArray pictures = resources.obtainTypedArray(R.array.pictures);
ArrayList<TracksFolder> tracksFolders = new ArrayList<>();
for (int i = 0; i < foldersName.length; i++) {
String folderName = foldersName[i];
int imageResource = pictures.getResourceId(i, -1);
ArrayList<Track> tracks = getArrayListOfTracks(resources, i, imageResource);
tracksFolders.add(new TracksFolder(folderName, imageResource, tracks));
}
pictures.recycle();
return tracksFolders;
}
/**
* @param resources need to get typedArray to get array of audio files names
* @param folderPosition passed to Track constructor
* @param imageResource passed to Track constructor
* Liked tracks are obtained from shared preferences
* @return array list of tracks for every folder
*/
private ArrayList<Track> getArrayListOfTracks(Resources resources, int folderPosition, int imageResource) {
TypedArray audioTracksTypedArray = resources.obtainTypedArray(R.array.audio_tracks);
int audioTracksId = audioTracksTypedArray.getResourceId(folderPosition, 0);
String[] audio = resources.getStringArray(audioTracksId);
audioTracksTypedArray.recycle();
TypedArray trackNamesTypedArray = resources.obtainTypedArray(R.array.track_names);
int trackNamesId = trackNamesTypedArray.getResourceId(folderPosition, 0);
String[] trackNames = resources.getStringArray(trackNamesId);
trackNamesTypedArray.recycle();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
ArrayList<Track> tracksInFolder = new ArrayList<>();
for (int i = 0; i < trackNames.length; i++) {
int audioResource = resources.getIdentifier(audio[i], "raw", this.getPackageName());
String trackName = trackNames[i].replace("_", " ");
boolean isLiked = sharedPreferences.getBoolean(String.valueOf(audioResource), false);
tracksInFolder.add(new Track(audioResource, trackName, imageResource, isLiked));
}
return tracksInFolder;
}
//todo убрать полосы в списках треков
}
更新类:
@NonNull
private ArrayList<TracksFolder> getTracksFoldersAndInitService(Bundle savedInstanceState) {
if (getIntent().getExtras() != null) { //activity is triggered via on back pressed
Bundle bundle = getIntent().getExtras();
tracksFolders = (ArrayList<TracksFolder>) bundle.getSerializable("tracksFolders");
} else if (savedInstanceState != null) { //this happens after screen is rotated
tracksFolders = (ArrayList<TracksFolder>) savedInstanceState.getSerializable("tracksFolders");
} else { //this happens if app is launched by user
tracksFolders = getTracksFoldersFromResources();
initService();
}
return tracksFolders;
}
@Nick Fortescue,@Ranjan,谢谢你们的建议,但 tracksFolders 永远不会为 NULL。我已经编辑了类(您可以在“更新的类:”下方看到它)并将 tracksFolders 实例化分离到另一个带有 @NonNull 注释的方法中。我已经用这些更改更新了应用程序,后来又用相同的日志获得了相同的 NPE。我知道这是在用户身上测试应用程序的最糟糕方式,但我别无选择。如果你是对的,日志会说在 getTracksFoldersAndInitService 方法中抛出了异常。但它没有。因此,问题出在适配器中。如果我错了,请纠正我。
最佳答案
GridAdapter.getCount()
中出现的 NullPointerException 并不意味着 getCount() 返回 null。这意味着它正在访问一个空值。由于您上传了代码(太棒了!),我们可以看到只有两个可能的问题:
trackFolders
是 null
,所以当您访问它时,您会得到一个 NPEtrackFolders
返回一个 null
整数,因此当它被转换为一个 int
时,您会得到一个 NPE第二个选项是不可能的,因为 ArrayList
上的 .size()
也返回一个 int,所以它必须是第一个选项。
trackFolders
在构造函数中设置,它在您的 onCreate()
方法中从 bundle、从保存的状态或从 getTracksFolders() 设置
。看起来 getTracksFolders()
无法返回 null,所以我猜测您的 Activity 是在将此设置为 null 的情况下启动的。我会在您的 onCreate() 方法中仔细检查这一点,如果发生这种情况,请采取适当的措施,也许用 new ArrayList()
替换它?
关于android - Google Play 控制台报告应用程序崩溃,我无法重现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53027956/
这是在 https://stackoverflow.com/questions/12639454/make-scalacheck-tests-deterministic 中作为“奖金问题”提出的,但没
我的项目使用 Angular 6 和 Leaflet 1.2。 我想重现当用户在 Leaflet map 上保持右键或左键单击时的拖动效果。例如,我希望在不断按下空格键时能够开始拖动 map 。 我已
我们正在将我们的用户身份验证从提供的 .NET 实现迁移到我们自己的系统。 我们希望能够支持存在于 aspNet_Membership 表中的旧密码。 Password 和 Salt 位于该表中,因此
我有一个二进制文件,它在 99% 的时间里都运行良好。有时,我无法理解,它会因这个输出而崩溃。在我重新启动之后,一切正常。 二进制是一个模板系统。它读取了一些带有占位符的模板,例如{%foo%} 或
我试图在 c 中重现 strcpy 的行为,我的问题是该函数有效但它在末尾附加了额外的东西。 char *ft_strcpy(char * dst, const char * src) { in
我最近遇到了可怕的 UserPreferenceChanged 事件 UI 卡住问题,随后我解决了可能的原因,例如: 调用单个控件而不是主应用程序表单(参见 https://stackoverflow
在 Scala 编程中,我可以读到 ==运算符的行为就像是这样定义的: final def == (that: Any): Boolean = if (null eq this) {null eq t
我正在和我的 friend 一起开发 Django 项目。该项目依赖于一些 python 模块。我在 virtualenv 中安装了 django 和其他依赖项。 django 项目的代码位于一个存储
关于spark的大多数问题都使用show作为代码示例,没有生成数据帧的代码,如下所示: df.show() +-------+--------+----------+ |USER_ID|locatio
我正在尝试重现 java.lang.OutOfMemoryError: unable to create new native thread但是使用 -Xss VM 参数。我猜想如果我们有大量线程,并
我正在尝试在自定义 alertView 中插入表格 View 。我需要实现与默认警报相同的样式。从 Debug View Hierarchy 我几乎复制了样式,但我无法弄清楚 Apple 如何设置模糊
标准是否保证如果 std::mt19937 被相同的数字播种,它会在所有平台上产生相同的数字序列? 换句话说,它的实现是否由标准明确定义,或者像 std::rand() 一样被视为实现细节? 最佳答案
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的
我有一个网站可以从 BingPreview/1.0b* 获得访问,这很可能是 Bing 的机器人。 我收到一个错误,它似乎无法找到我非常确定应该存在的 DOM 元素。我没有从任何其他浏览器(在所有主要
有谁知道如何重现 new Notes new scanning feature在 iOS 11 中?? AVFoundation 是否用于相机? 摄像头如何检测纸张/文档/卡片的形状? 他们如何实时放
您好! 作为使用 Objective-C 开发 iPhone 应用程序的初学者,我想知道重新创建 iPhone SMS 应用程序 UI(带有消息气泡等的用户界面)的最简单方法是什么 我考虑过将 UIT
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How can the built-in range function take a single argu
虽然这很可能是我自己犯的错误,但有人可以帮助我。我有一个包含 6 个数据点的极坐标图,在绘制时仅显示 5 个数据点。如果这是一个问题,我会在 GitHub 上打开 1,但我在想,如果它归结于我糟糕的代
我正在尝试使用 rCharts 重现简单的示例绘图库 sankey图表。我发现this example from scratch并尝试重现它,但是,我遇到了一些问题。 首先,我尝试在没有任何内容的情况
进入 Haskell,我试图重现 numpy's reshape 之类的东西与列表。具体来说,给定一个平面列表,将其 reshape 为一个 n 维列表: import numpy as np a =
我是一名优秀的程序员,十分优秀!