在我正在进行的学习过程中(这次是对话框),我发现这有效:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
虽然以下操作无效(在运行时因WindowManager $ BadTokenException而失败):
AlertDialog.Builder builder = new AlertDialog.Builder(this.getApplicationContext());
我不明白为什么,因为AlertDialog.Builder的the constructor被定义为接受Context作为参数,而不是Activity:
public AlertDialog.Builder(Context 上下文中)
使用上下文的构造函数 构建器和AlertDialog它 创建
我错过了什么?
答案 0 :(得分:24)
活动继承上下文。 AlertDialog.Builder指定一个Context参数,因为它可以由作为Context的子类的任何类使用,包括Activity,ListActivity,Service,......(这背后有一个常见的编码习惯用法 - 你可以了解更多关于它的信息通过阅读Joshua Bloch奇妙的Effective Java中的第I8项(关于接口和抽象类)。
getApplicationContext()返回应用程序的上下文,它与您的活动上下文大致相同 - 而“大部分”是让您失望的内容。细节尚不清楚,但这是一个广泛遇到的问题,典型的答案是使用将警报写入屏幕的上下文。请注意,这是不是 getApplicationContext()返回的那个。
现在如果你像我一样,你可能会说“但我在一个不从Activity继承的类中工作 - 这就是为什么我想首先使用getApplicationContext()为什么 - 呃!”我实际上并不像那样粗鲁地说话; p ...重点是我也来过这里。我修理它是这样的:1)问问自己“我是否在非活动类中使用了我的UI AlertDialog代码,因为我希望跨活动分享它......甚至可以跨ListActivities,Services,......?”。如果没有,嗯...你真的在代码中有AlertDialog UI调用,你不能保证可以访问UI(以及上下文)吗?如果是这样,请重新考虑您的设计。
假设您确实希望跨活动分享此课程,......答案会变得清晰。您希望您的类可以被各种调用者使用,每个调用者可能都有自己的上下文:因此调用者必须将其上下文作为参数传递给您的类:
myClass(Context theContext, ...) { ... }
然后,每个活动,服务等都会进行如下调用:
myClass(this, ...);
看起来很熟悉?
小心!如果您要共享代码,则必须考虑并行调用共享代码的不同调用的可能性,以及所有分支。这超出了我们的范围...
玩得开心:)
答案 1 :(得分:13)
AlertDialog是Dialog的子类,其中包含关联的Window,其中包含LayoutParams。其中一个参数是窗口type。默认类型为TYPE_APPLICATION_ATTACHED_DIALOG,需要父窗口。
与活动相关联的WindowManager配置为使用活动窗口作为父窗口。与应用程序关联的WindowManager没有关联的父窗口。
底线:要成功显示对话框,您必须将默认窗口类型更改为不需要父窗口的类型,或者必须使用具有关联父窗口的上下文。