空对象引用上的 void android.view.View.dispatchWindowVisibilityChanged(int)'

Posted

技术标签:

【中文标题】空对象引用上的 void android.view.View.dispatchWindowVisibilityChanged(int)\'【英文标题】:void android.view.View.dispatchWindowVisibilityChanged(int)' on a null object reference空对象引用上的 void android.view.View.dispatchWindowVisibilityChanged(int)' 【发布时间】:2017-09-03 10:37:03 【问题描述】:

我有一个 Activity A [MainActivity],我从它开始 Activity B [Videoplayer]案例 1: 点击 Activity A 中的视频缩略图 => 转到 Activity B => 播放视频几秒钟(重要:您需要播放视频几秒钟)=> 单击返回导航 => 返回到活动 A => 没有崩溃

案例 2: 点击活动 A 中的视频缩略图 => 转到活动 B => 缓冲区和视频开始播放 => 立即点击返回导航(重要:不要播放视频)= > 应用尝试返回 Activity A => 崩溃及其一致

注意:我没有在 Activity A 的 onResume() 中编写代码,只是为了确保我没有覆盖任何可能导致崩溃的 onResume() 相关代码。 堆栈跟踪不指向应用程序代码中的一行,它只显示来自 android 源库的堆栈跟踪。我为此花费了超过 4+小时,感谢您的帮助。

Activity B [玩家活动] 代码:

public class VitamioPlayerActivity extends AppCompatActivity implements MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnTimedTextListener 
public static final String TAG = VitamioPlayerActivity.class.getSimpleName();

@Bind(R.id.videoView)
VideoView videoView;

@Bind(R.id.progressBar)
ProgressBar progressBar;

@Bind(R.id.subtitle_view)
TextView mSubtitleView;

private VideoModel videoModel;
private long mPosition = 0;

private boolean isLiveChannel;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vitamio);
    ButterKnife.bind(this);
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

    if (getIntent() == null)
        return;

    if (getIntent().getExtras() == null)
        return;

    if (!getIntent().getExtras().containsKey(AppConstant.KEY_BUNDLE_VIDEO))
        return;

    videoModel = (VideoModel) getIntent().getExtras().getSerializable(AppConstant.KEY_BUNDLE_VIDEO);
    if (videoModel == null)
        return;

    playVideo();



VideoControllerView controllerView;

void playVideo() 
    String path = null;
    if (videoModel.isLoadBalancer()) 
        path = URLHelper.getInstance().getPlayableVideoUrl(videoModel.getVideoUrl());
     else
        path = videoModel.getVideoUrl();

    if (TextUtils.isEmpty(path)) 
        Toast.makeText(this, "Please edit MediaPlayer Activity, " + "and set the path variable to your media file path." + " Your media file must be stored on sdcard.", Toast.LENGTH_LONG).show();
        return;
    
    isLiveChannel = !(path.contains(".mp4"));
    videoView.setVideoURI(Uri.parse(path));
    videoView.setMediaController(controllerView = new VideoControllerView(this, !isLiveChannel));
    videoView.requestFocus();
    videoView.start();

    videoView.setOnPreparedListener(this);
    videoView.setOnErrorListener(this);


@Override
public void onPrepared(MediaPlayer mediaPlayer) 
    mediaPlayer.setPlaybackSpeed(1.0f);


@Override
public void onTimedText(String text) 
    mSubtitleView.setText(text);


@Override
public void onTimedTextUpdate(byte[] pixels, int width, int height) 
    int a = 1;



@Nullable
@OnClick(R.id.imvHeaderBack)
void doBack() 
    finish();


@Override
public void onBackPressed() 
    finish();


@Override
protected void onPause() 
    mPosition = videoView.getCurrentPosition();
    videoView.stopPlayback();
    super.onPause();


@Override
protected void onResume() 
    if (mPosition > 0) 
        videoView.seekTo((int) mPosition);
        mPosition = 0;
    
    super.onResume();


@Override
public boolean onError(MediaPlayer mp, int what, int extra) 
    WindowUtils.getInstance().genericInfoMsgWithOKCallBack(this, null, "Sorry, Cannot Play Video", R.color.redStatus,
            new ViewConstructor.InfoDisplayListener() 
                @Override
                public void onPositiveSelection(DialogInterface alertDialog) 
                    doBack();
                
            );
    return true;

堆栈跟踪:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.dispatchWindowVisibilityChanged(int)' on a null object reference
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1310)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1410)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1134)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6050)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:860)
    at android.view.Choreographer.doCallbacks(Choreographer.java:672)
    at android.view.Choreographer.doFrame(Choreographer.java:608)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:846)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5442)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

【问题讨论】:

请添加ActivityB代码 如果在A上崩溃,请添加A活动代码。 logcat 中还有其他信息吗?我曾经遇到过类似的问题是“在android代码中”......我不得不通过手动删除行(在onResume / OnActivityResult,......)代码来调试它,以便找到错误调用函数的确切行(可能传递一个空指针)导致错误。我认为你应该尝试一下。 好的@Feuby我也在添加活动A代码,如果我调试它不会崩溃,还有1点。时间是一个人玩的把戏,如果你仔细阅读我的问题,你会注意到 @DJphy,你的层次结构中有滚动条吗?像ScrollView 或其他一些带有滚动条的视图。禁用滚动条并尝试这种方式。 @azizbekian 好的,我会检查一下,听起来很有趣,我想我在 Activity A 中有一个滚动视图,谢谢 【参考方案1】:

在检查了更多文档之后,您似乎从 onCreate 文档中陷入了这种情况:https://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)

您可以在此函数中调用 finish(),在这种情况下,onDestroy() 将立即被调用,而不会执行任何其余的 Activity 生命周期(onStart()、onResume()、onPause() 等)。

由于您的onBackPresseddoBack 都调用finish(),您可能会遇到videoView 仍然在您的活动的onCreate 中开始的竞争条件,在onCreate 结束之前按下返回并且您的活动在尝试播放 videoView 时被破坏,同时跳过所有其他生命周期函数,导致这个奇怪的堆栈跟踪崩溃。

修复:覆盖 onResume 并在那里调用 videoView.start 并覆盖 onDestroyonStop 并在那里调用 if (videoView.isPlaying()) videoView.stopPlayback

【讨论】:

哦好的,试试看 我很幸运能从你那里得到答案,我会记住我作为 App Dev 的剩余旅程的金句——“在 onCreate() 完成之前完成活动”。继续努力,我读了这篇“随后回答问题以帮助填补尚未找到解决方案的问题的漏洞”,是的,你做到了。再次感谢 很高兴听到它对您有用!感谢您的复选标记:-)

以上是关于空对象引用上的 void android.view.View.dispatchWindowVisibilityChanged(int)'的主要内容,如果未能解决你的问题,请参考以下文章

尝试在空对象引用上调用虚拟方法 'void android.view.View.measure(int, int)'

尝试在空对象引用上调用虚拟方法“void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)”

Android ViewGroup 崩溃:尝试从空对象引用上的字段“int android.view.View.mViewFlags”读取

尝试从空对象引用上的字段“android.view.View androidx.recyclerview.widget.RecyclerView$ViewHolder.itemView”读取

尝试从空对象引用上的字段“android.view.View androidx.recyclerview.widget.RecyclerView$b0.a”读取

(android.view.View$OnClickListener)' 在一个空对象引用 Kotlin