Android - 在主布局完成显示后立即运行与UI相关的代码

时间:2015-10-25 08:05:28

标签: android android-layout android-asynctask

我正在编写我的第一个Android应用程序。我的主要布局上有ExpandableListView,需要一些时间来加载(~5s)。我需要在理论上显示UI之前或之后调用静态方法,但该方法绝对需要能够显示AlertDialog。从我的测试中,需要在显示任何AlertDialog之前显示UI,这是有道理的。

根据我的理解,应用程序会在onResume()返回时显示UI。但是,在onResume()返回后,似乎没有任何简单的方法可以在UI线程上执行代码,这样我可以显示AlertDialog而不是onPostExecute()来自AsyncTask {1}},它需要在我的测试中显示任何图形对话/ Toast之前返回,我无法做到。

我花了很多时间尝试OnGlobalLayoutListenerRunnableAsyncTask之类的事情,但我现在意识到这些都不会因各种原因而起作用而且我已经没有了想法。

编辑:代码

@Override
protected void onResume()
{
    super.onResume();
    MessageQueue.IdleHandler h = new MessageQueue.IdleHandler()
    {
        @Override
        public boolean queueIdle()
        {
            AlertDialog.Builder dlgAlert  = new AlertDialog.Builder(getBaseContext());
            dlgAlert.setMessage("This is an alert with no consequence");
            dlgAlert.setTitle("App Title");
            dlgAlert.setPositiveButton("OK", null);
            dlgAlert.setCancelable(true);
            dlgAlert.create().show();
            return true;
        }
    };
    this.getMainLooper().myQueue().addIdleHandler(h);
}

1 个答案:

答案 0 :(得分:1)

我找到了解决方案;它有效,但我相信它可以做得更好/更优雅。重申目标:我需要在显示主要活动的主要布局后立即运行显示对话框的代码。

此代码的作用:如果用户在主要布局显示后按下MyClass.doTask(args)的正按钮,则此代码允许您执行AlertDialog并显示ProgressDialog直到任务完成。

在您的工作线程中,您还可以使用static HashMap<Dialog, Boolean>或类似的东西轻松跟踪所有嵌入式对话框的状态(如果您有很多),但所有对话必须为static工作。

在您的主要活动类中:

private static boolean staticInitializerFired = false;
private static MyType staticArg = myVal;

@Override
protected void onResume()
{
    super.onResume();
    if(!staticInitializerFired)
    {
        staticInitializerFired = true;
        final Context ctx = this;
        Thread t = new Thread()
        {
            @Override
            public void run()
            {
                MyClass.staticMethod(ctx, staticArg);
            }
        };
        t.start();
    }
}

在MyClass中:

private static boolean dlg0Showing = true; //preset initial state so worker thread is notified correctly before the dialog is actually built and shown in the UI thread
private static boolean dlg1Showing = false;
private static ProgressDialog progressDialog;
private static void showDialogAndDoTask(final Context context)
{
    ((Activity)context).runOnUiThread(new Runnable()
    {
        @Override
        public void run()
        {
            AlertDialog dlg = new AlertDialog.Builder(context).create();
            dlg.setMessage("My message... Yes/No ?");
            dlg.setCancelable(false);
            dlg.setButton(AlertDialog.BUTTON_POSITIVE, "Yes",
                    new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int id)
                        {
                                                    dlg1Showing = true;
                    dlg0Showing = false;

                    progressDialog = ProgressDialog.show(context, "Info", "Doing task...", true);
                        }
                    });
            dlg.setButton(AlertDialog.BUTTON_NEGATIVE, "Continue regardless",
                    new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int id)
                        {
                            dlg0Showing = false;
                            dialog.dismiss();
                        }
                    });
            dlg.show();
            return;
        }
    });
    //wait for dialogs to have completed
    while(dlg0Showing)
    {
        try{Thread.sleep(500);}
        catch(Exception ex) {}
    }
    if(dlg1Showing)
    {
        doTask(args);
        progressDialog.dismiss();
    }
    //GC cleanup
    progressDialog = null;
}