如何在没有Activity上下文的情况下在android中显示对话框?

Man*_*ish 35 android android-alertdialog

这似乎应该很简单,但我在任何地方都找不到答案.我有一个Android应用程序,在后台执行网络任务.如果出现错误,我想显示错误对话框.当任务返回时,我不知道哪个Activity在前台.根据这篇文章,看起来我们不能使用应用程序上下文来显示一个对话框(事实上,如果我尝试的话,我确实会遇到崩溃).

那么我怎样才能获得当前活动的背景?同样,网络任务的接收器在Application上下文中运行,而不是在特定的Activity中运行.还有其他想法吗?

编辑:我应该澄清一下.如果我不是前台应用程序,我不想显示错误对话框.我只对我们的应用程序暂时处于前台的情况感兴趣.

Com*_*are 26

如果出现错误,我想显示错误对话框.

如果您知道用户正在使用您的应用程序,请仅执行此操作.如果你在其他东西中断它们(玩游戏,看电影,读书),用户将非常恼火.

那么我怎样才能获得当前活动的背景?

你没有.最多,你让当前的活动知道它需要做些什么.

还有其他想法吗?

一种可能性是使用有序广播,所以如果你有一个前台活动,它就会获得控制权,否则你会引发一个Notification让用户知道问题而不会弹出一个对话框.接收有序广播的活动可以显示AlertDialog或以其他方式让用户知道该问题.我在博客文章中写了关于如何执行此操作的详细信息(以及书籍章节),这是一个演示该技术的示例应用程序.

或者,进行服务调用startActivity()以启动以对话为主题的活动.


Mic*_*ger 8

虽然这个问题已经很老了,但如果您希望它与任何活动的Activity. 因此,您不需要Activities像其他答案中建议的那样注册个人。

我想强调的是,这通常是您应该尽量避免的事情 - 创建不知道视图上下文的对话框,但在特殊情况下这可能很有用。

通过使用此解决方案,ActivityLifecycleCallbacks您始终可以了解活动Activity级别Application。然后,您可以使用此活动从您只能访问该类的网络代码中Activity打开对话框或其他内容:ActivitiesApplication

class YourApplication : Application() {

    private val activeActivityCallbacks = ActiveActivityLifecycleCallbacks()

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(activeActivityCallbacks)
    }

    override fun onTerminate() {
       unregisterActivityLifecycleCallbacks(activeActivityCallbacks)
       super.onTerminate()
    }

    fun getActiveActivity(): Activity? = activeActivityCallbacks.getActiveActivity()
// ...
}


class ActiveActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {

   private var activeActivity: Activity? = null

   fun getActiveActivity(): Activity? = activeActivity

   override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
      activeActivity = activity
   }

   override fun onActivityDestroyed(activity: Activity) {
      if (activity === activeActivity) {
         activeActivity = null
      }
   }
// ...
}
Run Code Online (Sandbox Code Playgroud)

从任何地方:

YourApplication.get().getActiveActivity()?.let { activity ->
    activity.runOnUiThread {
       AlertDialog.Builder(activity).setMessage("test").show()
    }
}
Run Code Online (Sandbox Code Playgroud)

请检查其他 SO 帖子如何实现 getter Application:例如Kotlin 单例应用程序类


Man*_*ish 6

我创建了一个实现CommonsWare想法的帮助程序类.希望显示警报的活动只需要调用Alerts.register()和Alerts.unregister().然后任何人都可以调用Alerts.displayError().

欢迎评论.

public class Alerts {

    private static class AlertReceiver extends BroadcastReceiver {

        private static HashMap<Activity, AlertReceiver> registrations;
        private Context activityContext;

        static {
            registrations = new HashMap<Activity, AlertReceiver>();
        }

        static void register(Activity activity) {
            AlertReceiver receiver = new AlertReceiver(activity);
            activity.registerReceiver(receiver, new IntentFilter(MyApplication.INTENT_DISPLAYERROR));
            registrations.put(activity, receiver);
        }

        static void unregister(Activity activity) {
            AlertReceiver receiver = registrations.get(activity);
            if(receiver != null) {
                activity.unregisterReceiver(receiver);
                registrations.remove(activity);
            }
        }

        private AlertReceiver(Activity activity) {
            activityContext = activity;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            abortBroadcast();
            String msg = intent.getStringExtra(Intent.EXTRA_TEXT);
            displayErrorInternal(activityContext, msg);
        }
    }

    public static void register(Activity activity) {
        AlertReceiver.register(activity);
    }

    public static void unregister(Activity activity) {
        AlertReceiver.unregister(activity);
    }

    public static void displayError(Context context, String msg) {
        Intent intent = new Intent(MyApplication.INTENT_DISPLAYERROR);
        intent.putExtra(Intent.EXTRA_TEXT, msg);
        context.sendOrderedBroadcast(intent, null);
    }

    private static void displayErrorInternal(Context context, String msg) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("Error")
               .setMessage(msg)
               .setCancelable(false)
               .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       dialog.cancel();
                   }
               });
        final AlertDialog alert = builder.create();

        alert.show();
    }

}
Run Code Online (Sandbox Code Playgroud)