在什么情况下findViewById会突然返回null?

时间:2019-02-12 10:21:54

标签: android android-fragments

我有一个!!,我正在使用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()

...可能是线程问题吗?

2 个答案:

答案 0 :(得分:1)

如果给定的id不在您的关联视图中,则

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。