为什么AlertDialog.Builder(Context context)只接受Activity作为参数?

an0*_*00b 34 android android-context android-alertdialog android-activity

在我正在进行的学习过程中(这次是对话框),我发现这有效:

  AlertDialog.Builder builder = new AlertDialog.Builder(this);
Run Code Online (Sandbox Code Playgroud)

虽然以下方法不起作用(运行时因WindowManager $ BadTokenException而失败):

  AlertDialog.Builder builder = new AlertDialog.Builder(this.getApplicationContext());
Run Code Online (Sandbox Code Playgroud)

我不明白为什么,因为AlertDialog.Builder 的构造函数被定义为接受Context作为参数,而不是Activity:

public AlertDialog.Builder(Context context)

构造函数使用此构建器的上下文及其创建的AlertDialog.

我错过了什么?

DJC*_*DJC 25

活动继承Context.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, ...);

看起来熟悉?

小心点!如果您要共享代码,则必须考虑并行调用共享代码的不同调用的可能性,以及所有分支.这超出了我们的范围......

玩得开心 :)

  • "明确"的答案仍然存在问题,因为两个活动可能不一定只想共享相同的"类",他们可能想要共享该类的相同"实例".如果是这种情况,那么您不能让两个活动都使用自己的上下文创建共享类.这真是Android的一个可怕的设计选择.为什么你想要创建AlertDialogs,而不是让它们弹出所有活动?iOS允许您从任何地方抛出UIAlertViews.Android也应该. (13认同)

j__*_*__m 13

AlertDialogDialog的子类,它有一个关联的Window,它有一个关联的LayoutParams.其中一个参数是窗口类型.默认类型为TYPE_APPLICATION_ATTACHED_DIALOG,需要父窗口.

与Activity关联的WindowManager配置为使用Activity的窗口作为父窗口.与Application关联的WindowManager没有关联的父窗口.

底线:要成功显示对话框,您必须将默认窗口类型更改为不需要父窗口的类型,或者必须使用具有关联父窗口的上下文.