我有一个!!
,我正在使用Fragment
和它自己的ExoPlayer
,该主机由PlayerView
托管,该Activity
带有弹出的“对话框”视图,另外一个{{ 1}},我打算与之共享PlayerView
。这两个ExoPlayerInstance
都在布局XML中声明。
播放器本身在PlayerView
中声明。
当Fragment
的{{1}}借用Activity
时,可以很好地传输Player对象。但是,当PlayerView
将Player对象返回到Fragment
时,出于某种原因,Activity
中的Fragment
为空。
我知道我可以对PlayerView
进行null检查,但这可能无法解决根本原因-Fragment
的findViewById突然返回null的原因。
那么,这是怎么发生的,以及我如何解决或解决它?
编辑:
我用来在片段中借入/返回Player对象的代码:
PlayerView
该片段的XML基本上如下:
Fragment
如此处所示,片段的布局XML的视图ID为fun borrowPlayer(): SimpleExoPlayer {
vw_exo_player.player = null
vw_exo_player.fadeInvisible(100)
return player
}
fun returnPlayer() {
if(vw_exo_player != null) {
vw_exo_player.player = player
vw_exo_player.fadeVisible(100)
}
}
。
以上两个函数在Activity中调用:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/vw_exo_player"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:resize_mode="zoom"
app:surface_type="texture_view"
app:use_controller="false"
tools:visibility="invisible" />
...
</android.support.constraint.ConstraintLayout>
上面的vw_exo_player
主要在另一个Fragment中调用,而fun showPopupVideo(anchor: PopupVideoAnchor) {
if (popupVideoHolders[anchor]?.isOn == true) return
if (anchor == PopupVideoAnchor.WEB && (popupVideoHolders[PopupVideoAnchor.QNA]?.isOn == true || popupVideoHolders[PopupVideoAnchor.POLL]?.isOn == true)) {
return
}
Trace.i("Show Popup : $anchor")
if (pv_popup.player == null) {
pv_popup.player = findFragment(GameAVStreamFragment::class.java)?.borrowPlayer()
}
val x: Float = popupVideoHolders[anchor]?.x ?: 0F
val y: Float = popupVideoHolders[anchor]?.y ?: 0F
val w: Int = popupVideoHolders[anchor]?.w ?: 0
val h: Int = ((w.f / videoSize.w.f) * videoSize.h.f).i
val b: Float = if (popupVideoHolders[anchor]?.isBordered == true) 0.95F else 1F
val layoutParam = lay_popup_video.layoutParams
for (popupVideoHolder in popupVideoHolders) {
if (popupVideoHolder.value.isOn) {
loadAnimation(R.anim.fade_out).apply {
duration = 150
onEnd {
lay_popup_video.clipScale = 1F
lay_popup_video.x = x
lay_popup_video.y = y
lay_popup_video.layoutParams.width = w
lay_popup_video.layoutParams.height = h
lay_popup_video.requestLayout()
lay_popup_video_border.clipScale = b
popupVideoHolders[anchor]?.isOn = true
lay_popup_video.clearAnimation()
lay_popup_video.startAnimation(loadAnimation(R.anim.fade_in).apply { duration = 150 })
}
lay_popup_video.clearAnimation()
lay_popup_video.startAnimation(this)
}
return
}
}
popupVideoHolders[anchor]?.isOn = true
currPopupVideoAnim?.cancel()
currPopupVideoAnim = AnimatorSet().apply {
duration = 350L
onStart {
lay_popup_video.visible()
Trace.d("Start Popup Video Animation")
}
playTogether(
ObjectAnimator.ofFloat(lay_popup_video, "clipScale", lay_popup_video.clipScale, 1F),
ObjectAnimator.ofFloat(lay_popup_video, "x", lay_popup_video.x, x),
ObjectAnimator.ofFloat(lay_popup_video, "y", lay_popup_video.y, y),
ValueAnimator.ofInt(layoutParam.width, w).apply {
addUpdateListener {
val animW = it.animatedValue as Int
layoutParam.width = animW
lay_popup_video.requestLayout()
}
},
ValueAnimator.ofInt(layoutParam.height, h).apply {
addUpdateListener {
val animH = it.animatedValue as Int
layoutParam.height = animH
lay_popup_video.requestLayout()
}
},
ObjectAnimator.ofFloat(lay_popup_video_border, "clipScale", lay_popup_video_border.clipScale, b))
start()
}
}
fun closePopupVideo(anchor: PopupVideoAnchor) {
if (popupVideoHolders[anchor]?.isOn?.not() != false) return
popupVideoHolders[anchor]?.isOn = false
if (anchor == PopupVideoAnchor.WEB && (popupVideoHolders[PopupVideoAnchor.QNA]?.isOn == true || popupVideoHolders[PopupVideoAnchor.POLL]?.isOn == true)) {
return
}
val layoutParam = lay_popup_video.layoutParams
for (popupVideoHolder in popupVideoHolders) {
if (popupVideoHolder.value.isOn) {
loadAnimation(R.anim.fade_out).apply {
duration = 150
onEnd {
lay_popup_video.clipScale = 1F
lay_popup_video.x = popupVideoHolder.value.x
lay_popup_video.y = popupVideoHolder.value.y
lay_popup_video.layoutParams.width = popupVideoHolder.value.w
lay_popup_video.layoutParams.height = ((popupVideoHolder.value.w.f / videoSize.w.f) * videoSize.h.f).i
lay_popup_video.requestLayout()
lay_popup_video_border.clipScale = if (popupVideoHolder.value.isBordered) .95F else 1F
lay_popup_video.clearAnimation()
lay_popup_video.startAnimation(loadAnimation(R.anim.fade_in).apply { duration = 150 })
}
lay_popup_video.clearAnimation()
lay_popup_video.startAnimation(this)
}
return
}
}
currPopupVideoAnim?.cancel()
currPopupVideoAnim = AnimatorSet().apply {
duration = 350L
onEnd {
findFragment(GameAVStreamFragment::class.java)?.returnPlayer()
pv_popup.player = null
lay_popup_video.invisible()
}
playTogether(
ObjectAnimator.ofFloat(lay_popup_video, "clipScale", lay_popup_video.clipScale, 3.5F),
ObjectAnimator.ofFloat(lay_popup_video, "x", lay_popup_video.x, 0F),
ObjectAnimator.ofFloat(lay_popup_video, "y", lay_popup_video.y, 0F),
ValueAnimator.ofInt(layoutParam.width, videoSize.w).apply {
addUpdateListener {
val animW = it.animatedValue as Int
layoutParam.width = animW
lay_popup_video.requestLayout()
}
},
ValueAnimator.ofInt(layoutParam.height, videoSize.h).apply {
addUpdateListener {
val animH = it.animatedValue as Int
layoutParam.height = animH
lay_popup_video.requestLayout()
}
},
ObjectAnimator.ofFloat(lay_popup_video_border, "clipScale", lay_popup_video_border.clipScale, 3.5F))
start()
}
}
在10秒计时器结束时被调用:
showPopupVideo()
...可能是线程问题吗?
答案 0 :(得分:1)
FindViewById可能返回null。或者,如果您要在视图组上调用findviewbyid,则该视图组将不保存具有特定ID的视图。
答案 1 :(得分:0)
如果您使用的是在XML布局中不可用的id,则它将突然返回null。
例如
布局(XML):
<TextView
android:id="tv_sample"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
活动(Java):
Textview tvSample = findViewById(R.id.tv_sam);
检查布局和活动文件中声明的ID,以使其触发NullPointerException。