cur*_*zen 12 java android android-notifications android-fragments
如何决定Activity一个Notification应该启动如果目标可能取决于配置(屏幕大小,方向等); 当一个人使用Fragments 时经常出现这种情况?
让我们考虑一下NewsReader示例,演示如何使用Fragments生成一个可以很好地适应多种屏幕尺寸和方向的应用程序.此应用程序的结构如下:
HeadlinesFragment.ArticleFragment.NewsReaderActivity).在双窗格模式下,此活动包含两个片段.在单窗格模式下,它只包含HeadlinesFragment.ArticleActivity.此活动仅用于单窗格模式; 它包含了ArticleFragment.现在,假设我要增强此应用程序以添加Service侦听新闻更新的背景,并在有新消息时通过状态栏通知通知用户.合理的要求列表可能如下所示:
请注意,这些要求会根据当前配置转换为不同的目标活动.特别是,
NewsReaderActivity.NewsReaderActivity.ArticleActivity.实现上述(2)和(3)的优雅方式是什么?我认为可以安全地排除Service探测当前配置的可能性,以决定用什么活动来定位PendingIntent.
我想到的一个解决方案是跳过(2)并且总是做(3) - 即,ArticleActivity如果只有一个新闻更新,则始终启动.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;
}
//...
//...
}
Run Code Online (Sandbox Code Playgroud)
此代码确保如果正在查看ArticleActivity,但切换到不再需要它的配置(例如从纵向到横向); 然后活动简单关闭.
但是,这在我们的情况下不起作用,因为意图将FLAG_ACTIVITY_NEW_TASK设置标志; 我们会创建一个新任务,并且堆栈上没有"先前"活动.所以,调用finish()只会清除整个堆栈.
那么,如果要启动的活动取决于屏幕配置,如何决定从通知启动哪些活动?
这是一个非常好的问题!
我认为可以安全地排除服务探测当前配置的可能性,以决定使用PendingIntent定位的活动.
我同意最好在UI层保持UI决策,但让服务做出决定肯定是一个权宜之计.您可以在UI层类上使用静态方法,以将决策代码保留在服务之外(例如,服务用于构建其的静态createArticlePendingIntent()方法).NewsReaderActivityNotification
那么,如果要启动的活动取决于屏幕配置,如何决定从通知启动哪些活动?
在你的内容中使用getActivity() PendingIntentfor ,有足够的额外内容,知道它在这个"显示文章"场景中.在它呼叫之前,让它确定是否是正确的答案.如果是这样,调用启动,然后调用以摆脱它自己(或不,如果你想从文章中转回去).NewsReaderActivityNotificationNewsReaderActivitysetContentView()ArticleActivityNewsReaderActivitystartActivity()ArticleActivityfinish()NewsReaderActivity
或者,在你的使用中使用getActivity() PendingIntentfor .有,所以它没有UI.它决定是启动还是调用正确的答案然后调用.与先前解决方案相比的优点是,如果最终目的地没有短暂的闪现.ICanHazArticleActivityNotificationICanHazArticleActivityTheme.NoDisplayNewsReaderActivityArticleActivitystartActivity()finish()NewsReaderActivityArticleActivity
或者,使用createArticlePendingIntent()我在答案的第一段中提到的选项.
可能还有其他选择,但这些都是我想到的.
当我在我的应用程序中使用双窗格/单窗格方法时,我只使用一个活动.在这种情况下,它意味着摆脱ArticleActivity.以下是您可以继续的方式:
首先,您可以通过使用不同配置的XML布局来控制片段的外观,例如:
单个窗格(res/layout):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/mainFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
双窗格(res/layout-xlarge-land):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/mainFragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="fill_parent" />
<FrameLayout
android:id="@+id/detailsFragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
在NewsReaderActivity中,您只需要检查布局中存在哪些片段:
boolean isMainFragment = (findViewById(R.id.mainFragment) != null);
if (isMainFragment) {
mainFragment = new ListFragment();
}
boolean isDetailFragment = (findViewById(R.id.detailsFragment) != null);
if (isDetailFragment) {
detailFragment = new DetailsFragment();
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (isMainFragment ) {
transaction.add(R.id.mainFragment, mainFragment);
}
if (isDetailFragment ) {
transaction.add(R.id.detailFragment, detaislFragment);
}
transaction.commit();
Run Code Online (Sandbox Code Playgroud)
然后,当您处于单窗格模式(detailsFragment not existing)并且想要显示详细信息屏幕时,您只需再次启动相同的活动,但在意图中包含一个参数,以告知需要哪些内容:
void onViewDetails() {
Intent i = new Intent(this, NewsReaderActivity.class);
i.putExtra("showDetails", true);
startActivity(i);
}
Run Code Online (Sandbox Code Playgroud)
在您的活动的onCreate()中,您可以根据此参数选择片段:
boolean isDetailFragment = (findViewById(R.id.detailsFragment) != null);
if (!isDetailFragment) {
boolean showDetails = getIntent().getBooleanExtra("showDetails", false);
if (showDetails) {
mainFragment = new DetailsFragment();
}
else {
mainFragment = new ListFragment();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当您最终从通知中启动活动时,您就不再关心当前的屏幕方向了!
只需在你的意图中包含"showDetails"标志并将其设置为适当的,就像它完成的那样onViewDetails().然后,当您处于双窗格模式时,您的活动将显示两个片段(如果"showDetails"为true,您仍然可以执行某些特殊操作),或者当您处于需要单一痛苦模式的配置中时,此时您指定的片段显示"showDetails"标志.
我希望这会有所帮助,并让您对这种方法有一个很好的理解.
| 归档时间: |
|
| 查看次数: |
4609 次 |
| 最近记录: |