问题:
如果目标可能取决于配置(屏幕大小,方向等),如何决定应启动哪种Activity?当人们使用Notification时经常会发生这种情况?

细节:
让我们考虑NewsReader sample,它演示了如何使用Fragment来生成可以在多种屏幕尺寸和方向下正常播放的应用程序。这个程序的结构如下:

  • 一个Fragment
  • 一个HeadlinesFragment
  • 一个“主要” Activity (ArticleFragment)。在双 Pane 模式下,此 Activity 包含两个片段。在单 Pane 模式下,它仅包含NewsReaderActivity
  • 一个HeadlinesFragment。此 Activity 仅在单 Pane 模式下使用。它包含ArticleActivity

  • 现在,假设我要增强此应用程序,以添加一个后台ArticleFragment来侦听新闻更新,并在有新新闻项时通过状态栏通知通知用户。合理的需求 list 可能如下所示:
  • 如果有多个新闻更新,则单击通知应始终将用户带到头条新闻列表。
  • 如果只有一个更新,则单击通知应打开全新的新闻文章。

  • 请注意,这些要求会根据当前配置转换为不同的目标 Activity 。特别是,

    两种模式下的
  • 要求(1)= Service
  • 双 Pane 模式下的
  • 要求(2)= NewsReaderActivity
  • 单 Pane 模式下的要求(2)= NewsReaderActivity

  • 实现上述(2)和(3)的一种优雅方法是什么?我认为可以安全地排除ArticleActivity对当前配置进行探测的可能性,以决定使用Service定位的 Activity 。
    我想到的一种解决方案是跳过(2)并始终执行(3)-即,如果只有一个新闻更新,则始终启动PendingIntent。 ArticleActivity的此片段看起来很有希望:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...
        //...
        // If we are in two-pane layout mode, this activity is no longer necessary
        if (getResources().getBoolean(R.bool.has_two_panes)) {
            finish();
            return;
        }
    
        //...
        //...
    }
    
    此代码可确保如果正在查看ArticleActivity,但切换到不再需要的配置(例如,从纵向到横向);然后 Activity 简单结束。
    但是,这在我们的情况下不起作用,因为该意图将设置ArticleActivity标志;我们将创建一个新任务,并且堆栈上没有“先前” Activity 。因此,调用FLAG_ACTIVITY_NEW_TASK 只会清除整个堆栈。
    因此,如果要启动的 Activity 取决于屏幕配置,则如何确定从通知启动的 Activity ?

    最佳答案

    这是一个非常好的问题!



    我同意将UI决策保留在UI层是可取的,但是让服务做出决策无疑是一个权宜之计。您可能会在UI层类上使用静态方法来将决策代码严格地保留在服务之外(例如,服务用于构建其createArticlePendingIntent()NewsReaderActivity上的静态Notification方法)。



    getActivity()中的PendingIntent中使用NewsReaderActivity Notification,并有足够的额外内容,以便NewsReaderActivity知道它在此“显示文章”方案中。在调用setContentView()之前,让它确定ArticleActivity是否是正确的答案。如果是这样,NewsReaderActivity会调用startActivity()来启动ArticleActivity,然后会调用finish()摆脱自身(或者,如果您希望从本文中返回到NewsReaderActivity,则不会这样做)。

    或者,在getActivity()中为PendingIntent使用ICanHazArticleActivity NotificationICanHazArticleActivity具有Theme.NoDisplay,因此它将没有UI。它决定是启动NewsReaderActivity还是ArticleActivity,在正确的答案上调用startActivity(),然后调用finish()。与先前解决方案相比的优势在于,如果最终目标是NewsReaderActivity,则不会短暂闪烁ArticleActivity

    或者,使用我在答案第一段中提到的createArticlePendingIntent()选项。

    也许还有其他选择,但是这些都是我想到的。

    07-26 01:16