试图在MainActivity之外膨胀PopupWindow

时间:2013-03-30 18:28:06

标签: java android popupwindow

我正在尝试在MainActivity类之外充气PopupWindow。我能够在MainActivity中对它进行充气,但是当我尝试在它之外进行时我会收到以下错误。

  

致命异常:主要E / AndroidRuntime(7820):   android.view.WindowManager $ BadTokenException:无法添加窗口 -   令牌null无效;你的活动在运行吗?

以下方法适用于MainActivity:

public void popUp() {
    LayoutInflater layoutInflater 
    = (LayoutInflater)this
    .getSystemService(MyGameActivity.LAYOUT_INFLATER_SERVICE);  
    View popupView = layoutInflater.inflate(R.layout.gameover, null);  
    PopupWindow popupWindow = new PopupWindow(
            popupView, 
            LayoutParams.WRAP_CONTENT,  
            LayoutParams.WRAP_CONTENT);  
    popupWindow.showAtLocation(popupView, 0, 87, 120);
}

下面的方法是我试图在MainActivity类之外使用的方法(这个给出了错误):

public void popUp(Context context) {
    LayoutInflater layoutInflater 
    = (LayoutInflater)context
    .getSystemService(MyGameActivity.LAYOUT_INFLATER_SERVICE);  
    View popupView = layoutInflater.inflate(R.layout.gameover, null);  
    PopupWindow popupWindow = new PopupWindow(
            popupView, 
            LayoutParams.WRAP_CONTENT,  
            LayoutParams.WRAP_CONTENT);  
    popupWindow.showAtLocation(popupView, 0, 87, 120);
}

我知道如何让这个PopupWindow在我的MainActivity之外工作吗?

---编辑

LogCat结果:

03-30 19:53:18.596: W/dalvikvm(8437): threadid=1: thread exiting with uncaught exception (group=0x4001d560)
03-30 19:53:18.596: E/AndroidRuntime(8437): FATAL EXCEPTION: main
03-30 19:53:18.596: E/AndroidRuntime(8437): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.view.ViewRoot.setView(ViewRoot.java:533)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.widget.PopupWindow.invokePopup(PopupWindow.java:907)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.widget.PopupWindow.showAtLocation(PopupWindow.java:767)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at nl.saxion.act.playground.GameView.popUp(GameView.java:314)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at nl.saxion.act.playground.GameView.movePlayerLeft(GameView.java:299)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at nl.saxion.act.playground.MyGameActivity$1.onClick(MyGameActivity.java:93)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.view.View.performClick(View.java:2538)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.view.View$PerformClick.run(View.java:9152)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.os.Handler.handleCallback(Handler.java:587)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.os.Looper.loop(Looper.java:130)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at android.app.ActivityThread.main(ActivityThread.java:3687)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at java.lang.reflect.Method.invokeNative(Native Method)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at java.lang.reflect.Method.invoke(Method.java:507)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
03-30 19:53:18.596: E/AndroidRuntime(8437):     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:2)

在这里:

context = MyGameActivity.getContext(); //<< 

这不是在非Activity类中获取Activity of Context的正确方法(在普通的java类中)。您只需要使用context参数创建popUp()并将Activity上下文从Activity传递给popUp()方法:

public void popUp(Context context) {
    this.context = context;
    /....your code here
}

并通过将上下文传递为:

从MainActivity调用popUp方法
popUpClass popObj=new popUpClass();
popObj.popUp(MainActivity.this);

答案 1 :(得分:0)

在你的第二种方法

 MyGameActivity.getContext(); 

是指包含MyGameActivity类实例的静态方法。这是一个非常糟糕的主意。

实际上,你应该理解,一开始需要时间,Android活动或碎片,一般上下文,都有一个生命周期。这意味着一旦它们被停止,它们就不应再被使用了。这将有两个副作用:

  • 您可以防止此实例被垃圾收集,因为您持有对它的引用,从而污染内存。
  • 此上下文无法使用,使用它可以,并且会创建与内存泄漏,对话框泄漏等相关的错误。

所以,不要使用你的第二种方法。关闭活动时,对活动保持引用没有意义。

这里的解决方案是在每个需要它的活动中添加第一个方法,或者将它放在一个共同的超类中。然后它将始终与活动类的“当前/生动”实例相关。

另一种方法是为方法提供一个上下文,并始终将其传递给当前的活动活动。

--- BTW

LayoutInflater layoutInflater 
= (LayoutInflater)this
.getSystemService(MyGameActivity.LAYOUT_INFLATER_SERVICE);  

可写:

LayoutInflated.from( this );