gym*_*hoe 652 android builder android-context android-alertdialog
我的Activity正在尝试创建一个AlertDialog,它需要一个Context作为参数.如果我使用,这可以按预期工作:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Run Code Online (Sandbox Code Playgroud)
但是,我很谨慎地使用"this"作为上下文,因为当Activity被销毁并重新创建甚至在屏幕旋转之类的简单事件时,可能会发生内存泄漏.来自Android开发者博客上的相关帖子:
有两种简单的方法可以避免与上下文相关的内存泄漏.最明显的一个是避免在其自身范围之外逃避上下文.上面的例子显示了静态引用的情况,但内部类及其对外部类的隐式引用可能同样危险.第二种解决方案是使用Application上下文.只要您的应用程序处于活动状态并且不依赖于活动生命周期,此上下文就会存在.如果您计划保留需要上下文的长期对象,请记住应用程序对象.您可以通过调用Context.getApplicationContext()或Activity.getApplication()轻松获取它.
但是对于这AlertDialog()
两者来说,getApplicationContext()
或者getApplication()
作为一个Context是可接受的,因为它抛出异常:
"无法添加窗口 - 令牌null不适用于应用程序"
那么,这真的应该被视为一个"错误",因为我们被正式建议使用Activity.getApplication()
,但它没有宣传的功能吗?
吉姆
Ste*_*n L 1324
而不是getApplicationContext()
,只是使用ActivityName.this
.
Tru*_*oke 189
使用this
对我不起作用,但MyActivityName.this
确实如此.希望这可以帮助任何无法this
上班的人.
cod*_*zjx 56
您可以继续使用getApplicationContext()
,但在使用之前,您应该添加此标志:dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
,并且不会显示错误.
将以下权限添加到清单:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Run Code Online (Sandbox Code Playgroud)
ONE*_*ONE 35
当你说"...对于AlertDialog()时,你已经正确地确定了问题,getApplicationContext()或getApplication()都不能作为Context接受,因为它抛出了异常:'无法添加窗口 - 令牌null不适用于一个应用程序'"
要创建对话框,您需要活动上下文或服务上下文,而不是应用程序上下文(getApplicationContext()和getApplication()都返回应用程序上下文).
以下是您获取活动背景的方式:
(1)在活动或服务中:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2)在片段中:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
内存泄漏不是"this"引用固有的问题,"this"引用是对象对自身的引用(即引用用于存储对象数据的实际分配的内存).它发生在任何已分配的内存中,垃圾收集器(GC)在分配的内存耗尽其使用寿命后无法释放.
大多数情况下,当变量超出范围时,GC将回收内存.但是,即使在对象已经超过其使用寿命之后,对变量持有的对象(即"x")的引用仍然存在时,可能会发生内存泄漏.只要"x"持有对它的引用,分配的内存就会丢失,因为只要该内存仍被引用,GC 就不会释放内存.有时,由于对分配的内存的引用链,内存泄漏不明显.在这种情况下,GC将不会释放内存,直到删除了对该内存的所有引用.
为防止内存泄漏,请检查代码是否存在导致已分配内存被"this"(或其他引用)无限引用的逻辑错误.记得检查链引用.以下是一些可用于帮助您分析内存使用并找到那些讨厌的内存泄漏的工具:
Kev*_*oil 34
您的对话框不应该是"需要上下文的长期对象".文档令人困惑.基本上如果你做的事情如下:
static Dialog sDialog;
Run Code Online (Sandbox Code Playgroud)
(注意静态)
然后在你做过的某个活动中
sDialog = new Dialog(this);
Run Code Online (Sandbox Code Playgroud)
您可能会在轮换期间泄漏原始活动或类似会破坏活动.(除非你在onDestroy中清理,但在这种情况下你可能不会使Dialog对象静态)
对于某些数据结构,将它们设置为静态并基于应用程序的上下文是有意义的,但通常不适用于与UI相关的事物,如对话框.所以像这样:
Dialog mDialog;
...
mDialog = new Dialog(this);
Run Code Online (Sandbox Code Playgroud)
很好,不应该泄漏活动,因为mDialog将被活动释放,因为它不是静态的.
Gru*_*rux 24
我必须通过构造函数在片段中显示的自定义适配器上发送我的上下文,并且遇到了getApplicationContext()的这个问题.我解决了它:
this.getActivity().getWindow().getContext()
在片段的onCreate
回调中.
Mah*_*man 23
在Activity中使用:
MyActivity.this
Run Code Online (Sandbox Code Playgroud)
在片段中:
getActivity();
Run Code Online (Sandbox Code Playgroud)
小智 20
在Activity
按钮的点击出一个对话框
Dialog dialog = new Dialog(MyActivity.this);
Run Code Online (Sandbox Code Playgroud)
为我工作.
Mik*_*nin 18
小黑客:你可以防止GC破坏你的活动(你不应该这样做,但它可以在某些情况下帮助.不要忘记设置contextForDialog
为null
不再需要时):
public class PostActivity extends Activity {
...
private Context contextForDialog = null;
...
public void onCreate(Bundle savedInstanceState) {
...
contextForDialog = this;
}
...
private void showAnimatedDialog() {
mSpinner = new Dialog(contextForDialog);
mSpinner.setContentView(new MySpinner(contextForDialog));
mSpinner.show();
}
...
}
Run Code Online (Sandbox Code Playgroud)
Muh*_*zan 14
只需使用以下内容:
对于 Java 用户
如果您正在使用活动 --> AlertDialog.Builder builder = new AlertDialog.Builder(this);
或者
AlertDialog.Builder builder = new AlertDialog.Builder(your_activity.this);
如果您正在使用片段 --> AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
对于 Kotlin 用户
如果您正在使用活动 --> val builder = AlertDialog.Builder(this)
或者
val builder = AlertDialog.Builder(this@your_activity.this)
如果您正在使用片段 --> val builder = AlertDialog.Builder(activity!!)
mua*_*aaz 13
如果您正在使用片段并使用AlertDialog/Toast消息,请在context参数中使用getActivity().
像这样
ProgressDialog pdialog;
pdialog = new ProgressDialog(getActivity());
pdialog.setCancelable(true);
pdialog.setMessage("Loading ....");
pdialog.show();
Run Code Online (Sandbox Code Playgroud)
小智 9
加入
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
Run Code Online (Sandbox Code Playgroud)
和
"android.permission.SYSTEM_ALERT_WINDOW"/>
在清单中
它现在对我有用.甚至关闭并打开应用程序后,当时给了我错误.
小智 9
我ProgressDialog
在一个片段中使用并且在getActivity().getApplicationContext()
作为构造函数参数传递时遇到此错误.改变它getActivity().getBaseContext()
也不起作用.
对我有用的解决方案是通过getActivity()
; 即
progressDialog = new ProgressDialog(getActivity());
小智 6
如果您不在Activity之外,那么您需要在函数"NameOfMyActivity.this"中使用Activity作为活动,例如:
public static void showDialog(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage("Your Message")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
}
//Outside your Activity
showDialog(NameOfMyActivity.this);
Run Code Online (Sandbox Code Playgroud)
尝试使用对话框中活动的上下文。但是使用“ this”关键字时要小心,因为它不会每次都起作用。
例如,如果您将TabActivity作为具有两个选项卡的主机,并且每个选项卡都是另一个活动,并且如果您尝试从其中一个选项卡(活动)创建对话框,并且使用“ this”,那么您将获得异常,案例对话框应连接到承载所有活动且可见的主机活动。(您可以说大多数可见的父活动的上下文)
我没有尝试从任何文档中找到此信息。这是我没有深厚背景的解决方案,如果有人具有更好的知识,请随时发表评论。
对于未来的读者,这应该有所帮助:
public void show() {
if(mContext instanceof Activity) {
Activity activity = (Activity) mContext;
if (!activity.isFinishing() && !activity.isDestroyed()) {
dialog.show();
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
361493 次 |
最近记录: |