Android:ProgressDialog.show()与getApplicationContext崩溃

时间:2009-10-13 17:41:20

标签: android progressdialog

我似乎无法理解为什么会这样。这段代码:

mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);

工作得很好。但是,这段代码:

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

抛出以下异常:

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方法调用它的。

18 个答案:

答案 0 :(得分:127)

我正在使用API​​级别为7的Android版本2.1。我遇到了这个(或类似的)问题并使用此解决了:

Dialog dialog = new Dialog(this);

而不是:

Dialog dialog = new Dialog(getApplicationContext());

希望这会有所帮助:)

答案 1 :(得分:64)

对我而言,改变了

builder = new AlertDialog.Builder(getApplicationContext());

builder = new AlertDialog.Builder(ThisActivityClassName.this);

奇怪的是,第一个可以在谷歌教程中找到,人们会在这上面得到错误..

答案 2 :(得分:42)

您使用的是哪个API版本?如果我对问题是对的,那么这在Android 1.6(API版本4)中得到修复。

看起来getApplicationContext()正在返回的对象引用只指向null。我认为你遇到的问题类似于我所拥有的问题,onCreate()中的一些代码在窗口实际构建之前正在运行。这将是一个黑客,但尝试在几百毫秒内启动一个新线程(IIRC:300-400似乎对我有用,但你需要修补)打开你的ProgressDialog并启动你需要的任何其他东西(例如,网络IO)。像这样:

@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
}

答案 3 :(得分:23)

我不认为这是关于空应用程序上下文的时间问题

尝试在您的应用中扩展应用(或者只在您拥有时使用它)

public class MyApp extends Application

使实例可用作私有单例。这是永不为空

private static MyApp appInstance;

在MyApp中创建一个静态助手(将使用单例)

    public static void showProgressDialog( CharSequence title, CharSequence message )
{
    prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This!
}

<强> BOOM !!

另外,请在此处查看android工程师的答案:WindowManager$BadTokenException

  

此错误的一个原因可能是尝试显示应用程序   窗口/对话框通过不是活动的上下文。

现在,我同意,该方法采用Context param而不是Activity是没有意义的。

答案 4 :(得分:10)

阅读上述答案后,我发现根据我的情况,以下问题解决了这个问题。

这引发了错误

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

基于之前的答案,表明上下文是错误的,我改变了getApplicationContext()以从传递给onClick方法按钮的View中检索上下文。

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

我不完全理解Java的工作方式,所以我可能错了,但我猜测,对于我的具体情况,原因可能与上述代码片段在Abstract Activity类中定义的事实有关;许多活动继承和使用,也许这有助于getApplicationContext()不返回有效的上下文? (只是一个猜测)。

答案 5 :(得分:6)

我正在创建一个带有分项叠加层的地图视图。我正在使用mapActivity创建我的itemizedoverlay:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

我发现当我的itemizedoverlay的onTap方法被触发时(当在mapview上点击位置时)我会得到“android.view.WindowManager $ BadTokenException:无法添加窗口 - 令牌null不适用于应用程序”异常)。

我发现如果我简单地将'this'而不是'getApplicationContext()'传递给我的构造函数,问题就会消失。这似乎支持alienjazzcat的结论。怪异。

答案 6 :(得分:4)

对于TabActivities中显示的活动,请使用 getParent()

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

而不是

final AlertDialog.Builder builder = new AlertDialog.Builder(this);

答案 7 :(得分:3)

尝试 -

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

答案 8 :(得分:3)

适用于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)方法之外创建的。

答案 9 :(得分:2)

(兼容性)片段存在类似的问题,其中getActivity()内使用ProgressDialog.show()会导致崩溃。我同意这是因为时间安排。

可能的解决办法:

mContext = getApplicationContext();

if (mContext != null) {
    mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true);
}

而不是使用

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

尽可能早地放置mContext,以便有更多时间来抓取上下文。仍然无法保证这将起作用,它只是降低了崩溃的可能性。如果它仍然不起作用,你将不得不诉诸计时器黑客(这可能会导致其他时间问题,如稍后解除对话框)。

当然,如果您可以使用thisActivityName.this,那么它会更稳定,因为this已经指向了某些内容。但在某些情况下,与某些Fragment架构一样,它不是一种选择。

答案 10 :(得分:2)

(供将来参考)

我认为这是因为应用程序上下文和活动上下文存在差异,如下所述:http://www.doubleencore.com/2013/06/context/

这意味着我们无法使用Application Context显示对话框。就是这样。

答案 11 :(得分:2)

要在活动中使用对话框,请按以下方式执行:

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;
}

那是^ _ ^

答案 12 :(得分:1)

我为解决这个问题所做的是为我存储全局数据的所有活动创建一个基类。在第一个活动中,我将上下文保存在基类中的变量中,如下所示:

基类

public static Context myucontext; 

从基类派生的第一个活动

mycontext = this

然后在创建对话框时使用mycontext而不是getApplicationContext。

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();

答案 13 :(得分:1)

如果您在片段中调用ProgressDialog.show(),则将mContext转换为Activity对我有用。

     ProgressDialog pd = new ProgressDialog((Activity) mContext);

答案 14 :(得分:0)

我已经实现了警报对话框,以便将异常投放到当前的活动视图中。无论何时我都这样做了

AlertDialog.Builder builder = new AlertDialog.Builder(context);

给出相同的窗口异常。我在onCreate()之外编写警报代码。这么简单我在context = this;方法中的setContentView()语句之后使用onCreate()。将上下文变量视为全局类似{ {1}}

代码示例

Context context;

警报方法示例

static Context context;

 public void onCreate(Bundle savedInstanceState)  { 
        super.onCreate(savedInstanceState); 


        setContentView(R.layout.network); 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        context = this;
.......

它对我来说很好。实际上我在StackOverflow上搜索了这个错误我发现了这个查询。在阅读了这篇文章的所有回复之后,我尝试了这种方式,所以它有效。我认为这是一个克服异常的简单解决方案。

谢谢, Rajendar

答案 15 :(得分:0)

如果您对群组活动有疑问,请不要使用此功能。 PARENT是父活动组的静态。

final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);

而不是

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

答案 16 :(得分:0)

始终创建对话框并将其显示为活动的一部分。您需要传入Activity上下文而不是Application上下文。

http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog

答案 17 :(得分:0)

这是一个常见问题。 使用this代替getApplicationContext() 那应该可以解决您的问题