Android:ProgressDialog.show()使用getApplicationContext崩溃
我似乎无法理解为什么会发生这种情况。 此代码:
mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);
工作得很好。 但是,这个代码:
mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);
引发以下exception:
W/WindowManager( 569): Attempted to add window with non-application token WindowToken{438bee58 token=null}. Aborting. D/AndroidRuntime( 2049): Shutting down VM W/dalvikvm( 2049): threadid=3: thread exiting with uncaught exception (group=0x4001aa28) E/AndroidRuntime( 2049): Uncaught handler: thread main exiting due to uncaught exception E/AndroidRuntime( 2049): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tastekid.TasteKid/com.tastekid.TasteKid.YouTube}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application E/AndroidRuntime( 2049): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401) E/AndroidRuntime( 2049): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417) E/AndroidRuntime( 2049): at android.app.ActivityThread.access$2100(ActivityThread.java:116) E/AndroidRuntime( 2049): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794) E/AndroidRuntime( 2049): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 2049): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 2049): at android.app.ActivityThread.main(ActivityThread.java:4203) E/AndroidRuntime( 2049): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 2049): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime( 2049): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) E/AndroidRuntime( 2049): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) E/AndroidRuntime( 2049): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 2049): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application E/AndroidRuntime( 2049): at android.view.ViewRoot.setView(ViewRoot.java:460) E/AndroidRuntime( 2049): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177) E/AndroidRuntime( 2049): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) E/AndroidRuntime( 2049): at android.app.Dialog.show(Dialog.java:238) E/AndroidRuntime( 2049): at android.app.ProgressDialog.show(ProgressDialog.java:107) E/AndroidRuntime( 2049): at android.app.ProgressDialog.show(ProgressDialog.java:90) E/AndroidRuntime( 2049): at com.tastekid.TasteKid.YouTube.onCreate(YouTube.java:45) E/AndroidRuntime( 2049): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) E/AndroidRuntime( 2049): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364) E/AndroidRuntime( 2049): ... 11 more
任何想法为什么发生这种情况? 我从onCreate
方法调用这个。
你使用哪个API版本? 如果我对这个问题是正确的,那么在Android 1.6(API版本4)中已经解决了这个问题。
它看起来像getApplicationContext()
返回的对象引用只是指向null。 我认为你遇到了一个类似于我在onCreate()
中的一些代码在窗口实际完成之前运行的问题。 这将是一个黑客,但尝试启动一个新的线程在几百毫秒(IIRC:300-400似乎为我工作,但你需要修补),打开你的ProgressDialog,并开始你需要的任何东西(例如networkingIO)。 像这样的东西:
@Override public void onCreate(Bundle savedInstanceState) { // do all your other stuff here new Handler().postDelayed(new Runnable() { @Override public void run() { mProgressDialog = ProgressDialog.show( YouTube.this.getApplicationContext(), "", YouTube.this.getString(R.string.loading), true); // start time consuming background process here } }, 1000); // starting it in 1 second }
我正在使用Android版本2.1与API级别7.我遇到了这个(或类似)的问题,并通过使用这个解决:
Dialog dialog = new Dialog(this);
而不是这个:
Dialog dialog = new Dialog(getApplicationContext());
希望这可以帮助 :)
对我来说工作正在改变
builder = new AlertDialog.Builder(getApplicationContext());
至
builder = new AlertDialog.Builder(ThisActivityClassName.this);
奇怪的是,第一个可以在谷歌教程中find,人们得到这个错误..
我不认为这是一个空应用程序上下文周围的时间问题
尝试在您的应用程序内扩展应用程序(或者如果您已经有了使用它)
public class MyApp extends Application
将实例作为私有单例提供。 这从来不是空的
private static MyApp appInstance;
在MyApp中创build一个静态帮助器(将使用单例)
public static void showProgressDialog( CharSequence title, CharSequence message ) { prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This! }
繁荣!!
此外,请检查出这里的Android工程师的答案: WindowManager $ BadTokenException
导致此错误的原因可能是尝试通过不是活动的上下文来显示应用程序窗口/对话框。
现在,我同意,这是没有意义的,该方法需要一个上下文参数,而不是活动..
读了上面的答案后,我发现对于我的情况下面的问题已经解决了。
这抛出了错误
myButton.setOnClickListener(new OnClickListener(){ public void onClick(View v) { MyDialogue dialog = new MyDialogue(getApplicationContext()); dialog.show(); } });
基于之前提出的上下文是错误的答案,我更改了getApplicationContext()以从传递到onClick方法的button的View中检索上下文。
myButton.setOnClickListener(new OnClickListener(){ public void onClick(View v) { MyDialogue dialog = new MyDialogue(v.getContext()); dialog.show(); } });
我不完全理解Java的工作原理,所以我可能是错的,但我猜测对于我的具体情况,原因可能与上面的代码片段在抽象活动类中定义的事实有关; inheritance和许多活动使用,也许这是由于getApplicationContext()不返回有效的上下文的事实? (只是猜测)。
我正在使用分项叠加创build一个地图视图。 我从我的mapActivity创build像这样的itemizedoverlay:
OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);
我发现,当我的itemizedoverlay的onTap方法被触发时(当在地图视图上点击位置时),我会得到“android.view.WindowManager $ BadTokenException:无法添加窗口 – 标记null不适用于应用程序”exception。
我发现如果我简单地通过'this'而不是'getApplicationContext()'给我的构造函数,问题就消失了。 这似乎支持alienjazzcat的结论。 奇怪的。
对于TabActivities中显示的活动,使用getParent()
final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
代替
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
对于Android 2.2
使用此代码:
//activity is an instance of a class which extends android.app.Activity Dialog dialog = new Dialog(activity);
代替这个代码:
// this code produces an ERROR: //android.view.WindowManager$BadTokenException: //Unable to add window -- token null is not for an application Context mContext = activity.getApplicationContext(); Dialog dialog = new Dialog(mContext);
备注:我的自定义对话框是在activity.onCreateDialog(int dialogId)
方法之外创build的。
尝试 –
AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
有(兼容性getActivity()
在ProgressDialog.show()
使用getActivity()
使其崩溃的片段的类似问题。 我同意这是因为时机。
一个可能的修复:
mContext = getApplicationContext(); if (mContext != null) { mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true); }
而不是使用
mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);
尽可能早地放置mContext,让它有更多的时间来抓取上下文。 这仍然不能保证,这只会减less崩溃的可能性。 如果它仍然不起作用,你将不得不采取计时器黑客(这可能会导致其他计时问题,如稍后解散对话框)。
当然,如果你可以使用this
或者ActivityName.this
,它就更加稳定,因为this
已经指向了一些东西。 但在某些情况下,像某些片段架构一样,这不是一种select。
(供将来参考)
我认为这是因为应用程序上下文和活动上下文存在差异,如下所述: http : //www.doubleencore.com/2013/06/context/
这意味着我们不能使用应用程序上下文显示对话框。 而已。
要在活动中使用对话框,可以这样做:
private Context mContext; private AlertDialog.Builder mBuilder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; //using mContext here refering to activity context mBuilder = new AlertDialog.Builder(mContext); //... //rest of the code //... }
为了在片段中使用对话框,可以这样做:
private Context mContext; private AlertDialog.Builder mBuilder; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View mRootView = inflater.inflate(R.layout.fragment_layout, container, false); mContext = getActivity(); //using mContext here refering to fragment's hosting activity context mBuilder = new AlertDialog.Builder(mContext); //... //rest of the code //... return mRootView; }
就是这样^ _ ^
我做了什么来解决这个问题是为我所有的存储全局数据的活动创build一个基类。 在第一个活动中,我将上下文保存在基类中的一个variables中,如下所示:
基类
public static Context myucontext;
从基类派生的第一个活动
mycontext = this
然后在创build对话框时使用mycontext而不是getApplicationContext。
AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();
如果您在片段中调用ProgressDialog.show(),则将mContext强制转换为Activity。
ProgressDialog pd = new ProgressDialog((Activity) mContext);
我已经实现了警报对话框,用于抛出当前活动视图的exception。每当我给出这样的结果
AlertDialog.Builder builder = new AlertDialog.Builder(context);
给定相同的窗口exception。我编写警报的onCreate()的代码,所以我使用context = this;
在onCreate()
方法中的setContentView()
语句之后。将上下文variables视为全局Context context;
代码示例是
static Context context; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.network); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); context = this; .......
警报方法示例是
private void alertException(String execMsg){ Log.i(TAG,"in alertException()..."+context); Log.e(TAG,"Exception :"+execMsg); AlertDialog.Builder builder = new AlertDialog.Builder(context); .......
它对我来说工作得很好。实际上,我在StackOverflow上search了这个错误,我发现这个查询。阅读完这篇文章的所有回复之后,我尝试了这种方式,所以它工作。我认为这是一个简单的解决scheme来克服这个exception。
谢谢,Rajendar
如果你在groupActivity上有问题,不要使用这个。 PARENT是来自Parent ActivityGroup的静态的。
final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);
代替
final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
一个对话框总是被创build并显示为一个Activity的一部分。 您需要传递一个Activity上下文而不是Application上下文。
http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog