java - Android:即使对象在屏幕上,RecyclerView `getChildAt()` 也会返回 null
问题描述
我有一个包含 RecyclerView 的 Android 活动,基本上,我正在创建一个音乐播放器应用程序。在这里,上一首歌曲按钮应该是找到RecyclerView的前一个元素并点击它(这将播放歌曲),这样做,当我使用时recyclerView.getChildAt()
,它返回null,导致错误。
这是onClickListener
“上一个”按钮的代码...
prevSong_bottomSheet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// We start by checking if this is the first song or not!
if (songIndex.getCurrentIndex() == 0) {
Toast.makeText(MainActivity.this, "Nothing to play before this", Toast.LENGTH_SHORT).show();
// Now, this simply return as we don't want to execute any of the following code!
return;
}
Log.d(DEBUG_MESSAGE, "Original song index: " + songIndex.getCurrentIndex());
try {
// First, as we know that we'll be playing the previous audio, we start by decrementing
// the value inside `SongIndex`.
songIndex.prevSongPlayed();
// As the value inside `SongIndex` has been decremented, we use the same here!
View parentView = recyclerView.getChildAt(songIndex.getCurrentIndex());
// Now we extract the action button associated with this particular view!
Button tempButton = parentView.findViewById(R.id.music_actionButton);
// Now that we've got the button, instead of calling `startSong()` directly, we'll
// perform a click on the button, this way if we decide to perform some other action (in the future)
// once the user clicks that button, the action would still be valid!
tempButton.performClick();
Log.d(DEBUG_MESSAGE, "Previous song played successfully!");
} catch (NullPointerException e) {
// Lastly, if any error occurred in the above code, in the first line itself, we
// have already decremented SongIndex in the first line itself, thus, we increment
// it here to balance it out!
//songIndex.nextSongPlayed();
Log.d(DEBUG_MESSAGE, e.getLocalizedMessage() + "\n\n\n\n\n\n");
e.printStackTrace();
Log.d(DEBUG_MESSAGE, "Final song index: " + songIndex.getCurrentIndex());
}
}
});
运行上面的代码时,只要 RecyclerView 的下一个元素在屏幕上,它就可以正常运行,但是当视图离开屏幕时开始返回 null!
是的,我知道 RecyclerView 会破坏屏幕外的元素(甚至不创建它们)。为了解决这个问题,我尝试使用recyclerView.scrollToPosition()
,即使这样做了,它也会返回 null。我试图向上滚动到前一个元素的位置,甚至在它上方 2 或 3 个位置,仍然getChildAt()
返回 null。除此之外,我还尝试阻止主线程等待 RecyclerView 向上滚动(使用无限循环),即使在getChildAt()
返回 null 之后也是如此。
我该如何解决这个问题?
PSsongIndex
是一个类,它应该在当前播放的歌曲的位置上保持标签。这是它的代码(以防万一):
private class SongIndex {
/**
* This class is used to keep a track as to which song is being played currently, the data member
* created inside this class would be regularly updated using the functions defined below!
* Thus, this class will be used at various instances inside the program to know about the
* index of the song (inside the RecyclerView) which is being played currently!
*/
private int currentSongIndex;
public int getCurrentIndex() {
return currentSongIndex;
}
public void setCurrentSongIndex(int currentSongIndex) {
this.currentSongIndex = currentSongIndex;
}
public void nextSongPlayed() {
currentSongIndex++;
}
public void prevSongPlayed() {
currentSongIndex--;
}
}
PSS 我试图解决的另一件事是,当我到达屏幕顶部时(上面会有更多元素,但它们都不会出现在屏幕上,即 RecyclerView 可能会破坏它们),在那之后,我手动向上滚动,以便当前播放的歌曲位于屏幕中间(现在它上面有元素),即使是现在,当我尝试上一个按钮时,我仍然以某种方式结束了catch
部分:(
解决方案
根据您共享的代码, currentSongIndex 未初始化。它将有一些垃圾值,因此您的 if 条件 (songIndex.getCurrentIndex() == 0) 第一次将为 false,而 songIndex.getCurrentIndex() 将返回垃圾,因此 recyclerView.getChildAt(songIndex.getCurrentIndex()); 将为空
推荐阅读
- angular - 如何在angular2中获取http get请求发送域
- r - 如何在闪亮的应用程序中的fluidRow内的框元素中显示悬停
- angular - 角度服务在组件中的功能内使用
- postgresql - postgres`插入冲突更新`多列
- ios - 在 iOS xamarin 中将视频从 mov 转换为 MP4
- javascript - react-mapbox-gl 集群不工作
- c# - 是否可以从 aspnet 核心 Web 应用程序生成 .msi 包?
- algorithm - K近邻算法的分类
- amazon-web-services - 如何将 SSL 证书安装到 kubernetes 中的 aws 负载均衡器?
- java - java.lang.AssertionError:预期状态:<200> 但原为:<201>