首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用ViewGroup#addView和ViewGroup#removeView会导致NullPointerException

调用ViewGroup#addView和ViewGroup#removeView会导致NullPointerException
EN

Stack Overflow用户
提问于 2014-02-19 03:58:28
回答 1查看 786关注 0票数 5

在方法内部,我调用addViewremoveView,如下所示:

代码语言:javascript
复制
public class EnclosingClass extends FrameLayout {
    ...
    void fooMethod() {
        ...
        viewGroup1.addView(this);
        viewGroup2.removeView(this);
        ...
    }
    ...
}

这在纵向模式下工作得很好(它被调用了很多次,没有任何问题),但只要我将屏幕的方向改为横向,我就会得到一个NullPointerException:(仅供参考,在方向更改期间从surfaceChanged调用fooMethod ):

代码语言:javascript
复制
 18376         AndroidRuntime  E  FATAL EXCEPTION: main
 18376         AndroidRuntime  E  Process: com.google.android.apps.chrome, PID: 18376
 18376         AndroidRuntime  E  java.lang.NullPointerException
 18376         AndroidRuntime  E  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:405)
 18376         AndroidRuntime  E  at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 18376         AndroidRuntime  E  at android.view.View.layout(View.java:14817)
 18376         AndroidRuntime  E  at android.view.ViewGroup.layout(ViewGroup.java:4631)
 18376         AndroidRuntime  E  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 18376         AndroidRuntime  E  at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 18376         AndroidRuntime  E  at android.view.View.layout(View.java:14817)
 18376         AndroidRuntime  E  at android.view.ViewGroup.layout(ViewGroup.java:4631)
 18376         AndroidRuntime  E  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 18376         AndroidRuntime  E  at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 18376         AndroidRuntime  E  at android.view.View.layout(View.java:14817)
 18376         AndroidRuntime  E  at android.view.ViewGroup.layout(ViewGroup.java:4631)
 18376         AndroidRuntime  E  at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987)
 18376         AndroidRuntime  E  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744)
 18376         AndroidRuntime  E  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
 18376         AndroidRuntime  E  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
 18376         AndroidRuntime  E  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
 18376         AndroidRuntime  E  at android.view.Choreographer.doCallbacks(Choreographer.java:574)
 18376         AndroidRuntime  E  at android.view.Choreographer.doFrame(Choreographer.java:544)
 18376         AndroidRuntime  E  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
 18376         AndroidRuntime  E  at android.os.Handler.handleCallback(Handler.java:733)
 18376         AndroidRuntime  E  at android.os.Handler.dispatchMessage(Handler.java:95)
 18376         AndroidRuntime  E  at android.os.Looper.loop(Looper.java:136)
 18376         AndroidRuntime  E  at android.app.ActivityThread.main(ActivityThread.java:5017)
 18376         AndroidRuntime  E  at java.lang.reflect.Method.invokeNative(Native Method)
 18376         AndroidRuntime  E  at java.lang.reflect.Method.invoke(Method.java:515)
 18376         AndroidRuntime  E  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
 18376         AndroidRuntime  E  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
 18376         AndroidRuntime  E  at dalvik.system.NativeStart.main(Native Method)

为了解决这个问题,我将addViewremoveView放在一个Runnable中,如下所示:

代码语言:javascript
复制
void fooMethod() {
    ...
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            viewGroup1.addView(EnclosingClass.this);
            viewGroup2.removeView(EnclosingClass.this);
    });
    ...
}

这确实解决了问题,而且一切似乎都运行得很好,但我不明白为什么。将方法放在消息队列中如何帮助解决这个问题?另外,为什么在堆栈跟踪中看不到对我的代码的任何引用?我通过逐渐注释掉代码发现了这个问题。

EN

回答 1

Stack Overflow用户

发布于 2017-04-11 20:27:04

代码语言:javascript
复制
public final void runOnUiThread(Runnable action) {
    if (Thread.currentThread() != mUiThread) {
        mHandler.post(action);
    } else {
        action.run();
    }`enter code here`
}

因为你在真正的UIThread上使用runOnUiThread,所以代码运行在else分支:action.run()上,这是一个串行操作,其他.If仍然运行在带有本地mChildCount的UI线程上,所以会遇到空指针,(UI线程不安全)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21864041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档