2

我正在尝试在 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)
4

2 回答 2

2

在这里 :

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

this is not right way to get Context of Activity in non Activity class(in normal java class). you just need to create popUp() with context parameter and pass Activity context to popUp() method from Activity as:

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

and call popUp method from MainActivity by passing context as:

popUpClass popObj=new popUpClass();
popObj.popUp(MainActivity.this);
于 2013-03-30T18:32:09.240 回答
0

In your second method

 MyGameActivity.getContext(); 

refers to the static method that holds an instance of your MyGameActivity class. This is a very bad idea.

Indeed, you should understand, and it takes time at the beginning, that Android Activities or Fragments, Contexts in general, have a life cycle. This means that once they have been stopped, they should not be used any more. This would have 2 side-effets :

  • you prevent this instance from being garbage collected as you hold a reference to it, thus polluting memory.
  • this context can't be used and using it can, and will, create bugs related to memory leaks, dialog leaks, etc.

So, don't use your second method. It has no meaning to keep a reference on an activity when it has been closed.

The solution here is to add the first method in every activity that would need it, or put it in a common super class. Then it will always be related to the "current/vivid" instance of the activity class.

An alternative would be to provide you method a context and always pass it current active activity.

---BTW

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

can be written :

LayoutInflated.from( this );
于 2013-03-30T18:34:43.453 回答