基本的“片段教程”模式是这样的:
Fragments
,两者都位于同一Activity
。 Fragment
中列出Activity
。 Activity
启动新的Fragment
。(例如Android 3.0 Fragments API by Dianne Hackborn和Fragments API Guide)
在两台设备上,功能都在Fragments
中。 (简单)
在平板电脑上,整个应用 1 Activity
,在手机上,有多个{ {1}}
Activities
? 使用此方法的一个问题是,您复制了主平板电脑Activities
中的大量逻辑,以及单独的电话{{1 }}
Activity
进出(仅使用不同的布局)? 这种方式大多数逻辑都驻留在Activities
本身,并且只有一个Fragments
- 更少的代码重复。
我对Fragments
所了解的内容是它似乎最适合Activity
而不是ActionBarSherlock
(但我还没有使用它)。
教程是否过于简化,或者我错过了这种方法的主要内容?
我们已经在办公室成功地尝试了这两种方法 - 但我即将开始一个更大的项目,并希望尽可能让事情变得轻松。
相关问题的一些链接:
在问题上开始赏金 - 仍然不相信我为什么需要在平板电脑活动和每个电话活动中复制我的应用逻辑。
还找到了Square的一篇有趣的文章,非常值得一读:
答案 0 :(得分:41)
我同意教程非常简化。他们只是介绍Fragments
,但我不同意所建议的模式。
我也同意在多个活动中复制应用程序逻辑不是一个好主意(参见DRY Principle on wikipedia)。
我更喜欢ActionBarSherlock
片段演示应用(download here和source code here)使用的模式。与问题中提到的教程最匹配的演示是应用程序中名为“布局”的演示;或源代码中的FragmentLayoutSupport
。
在此演示中,逻辑已移出Activity
并移至Fragment
。 TitlesFragment
实际上包含更改片段的逻辑。这样,每个Activity都非常简单。要复制许多非常简单的活动,其中没有任何逻辑在活动中,这使得它非常简单。
通过将逻辑放入片段,不需要多次编写代码;无论片段放入哪个活动,它都可用。这使它成为比基本教程建议的模式更强大的模式。
/**
* Helper function to show the details of a selected item, either by
* displaying a fragment in-place in the current UI, or starting a
* whole new activity in which it is displayed.
*/
void showDetails(int index)
{
mCurCheckPosition = index;
if (mDualPane)
{
// We can display everything in-place with fragments, so update
// the list to highlight the selected item and show the data.
getListView().setItemChecked(index, true);
// Check what fragment is currently shown, replace if needed.
DetailsFragment details = (DetailsFragment) getFragmentManager()
.findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index)
{
// Make new fragment to show this selection.
details = DetailsFragment.newInstance(index);
// Execute a transaction, replacing any existing fragment
// with this one inside the frame.
FragmentTransaction ft = getFragmentManager()
.beginTransaction();
ft.replace(R.id.details, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
else
{
// Otherwise we need to launch a new activity to display
// the dialog fragment with selected text.
Intent intent = new Intent();
intent.setClass(getActivity(), DetailsActivity.class);
intent.putExtra("index", index);
startActivity(intent);
}
}
ABS模式的另一个优点是,您最终不会得到包含大量逻辑的Tablet活动,这意味着您可以节省内存。教程模式可以在更复杂的应用程序中导致非常大的主要活动;因为它需要随时处理放在其中的所有片段的逻辑。
总的来说,不要认为它被迫使用许多活动。可以把它想象成有机会将代码分成许多片段,并在使用它们时节省内存。
答案 1 :(得分:17)
我认为你走在正确的轨道上。 (是的,教程过于简化了。)
在平板电脑布局中,您可以使用单个活动并交换进出碎片(在多个“窗格”中)。在手机布局中,您可以为每个片段使用新的活动。
像这样:
这似乎是一项额外的工作,但通过为手机使用多项活动,您可以启用基本的Activity生命周期和Intent传递。这也允许框架处理所有动画和后栈。
为了帮助减少代码,您可以使用BaseActivity
并从中扩展。
因此,如果用户有平板电脑,您可以使用MyMultiPaneFragActivity
或类似内容。此活动负责管理片段的回调并将意图路由到正确的片段(例如搜索意图)
如果用户有手机,您可以使用非常少代码的常规活动,并将其扩展为MyBaseSingleFragActivity
或类似的内容。这些活动可能非常简单,5到10行代码(可能更少)。
棘手的部分是路由意图和诸如此类的东西。 *(编辑:见下文)。
我认为这是推荐方法的原因是节省内存并降低复杂性和耦合。如果要交换Fragments,FragmentManager
将为该堆栈维护对该Fragment的引用。它还简化了应该为用户“运行”的内容。此设置还将Fragment中的视图,布局和逻辑与Activity生命周期分离。这样,片段可以存在于单个活动中,与另一个片段(双窗格)或三窗格活动等中存在。
*具有常规意向路由的一个好处是,您可以从后端堆栈中的任何位置显式启动Activity。一个例子可能是搜索结果。 (MySearchResults.class)。
请阅读此处了解更多信息:
<强> http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html 强>
这可能是一个更前期的工作,因为每个片段必须在不同的活动中很好地工作,但它通常会得到回报。这意味着您可以使用定义不同片段组合的替代布局文件,保持片段代码模块化,简化操作栏管理,并让系统处理所有后台堆栈工作。
答案 2 :(得分:6)
以下是Reto Meier关于此问题的答案,取自this video Udacity's Android Fundamentals course。
有很多原因让您最好不要破坏自己的应用 不同的活动。
- 单一的整体活动会增加代码的复杂性,使其难以阅读,测试和维护。
- 使创建和管理意图过滤器变得更加困难。
- 增加了紧密耦合独立组件的风险。
- 如果单个活动包括敏感信息和可安全共享的信息,则更有可能引入安全风险。
一个好的经验法则是在上下文发生变化时创建一个新活动。例如,显示不同类型的数据,同时从查看切换到输入数据。
答案 3 :(得分:4)
此方法的一个问题是,您复制了主Tablet活动中的大量逻辑,以及单独的电话活动中的逻辑。
在主 - 细节模式中,有两个活动。一个在较大屏幕上显示两个片段,在较小屏幕上仅显示“主”片段。另一个在较小的屏幕上显示“细节”片段。
您的详细逻辑应该绑定在详细信息片段中。因此,活动之间没有与细节逻辑相关的代码重复 - 细节活动仅显示细节片段,可能传递来自Intent
额外的数据。
我读到的关于ActionBarSherlock的内容是它似乎最适合使用Fragments而不是Activities(但我还没有使用它)。
ActionBarSherlock与片段的关系不再是本机操作栏,因为ActionBarSherlock纯粹是本机操作栏的后端。
答案 4 :(得分:0)
参考第一个问题&#34;是否有理由将手机应用程序拆分为多个活动?&#34; - 是的它简单地归结为可用空间,平板电脑为开发人员提供了更多空间,从而允许开发人员在一个屏幕上放置更多空间。 Android告诉我们Activities can provide a screen。因此,平板电脑上的1个大屏幕可以做什么,可能必须分布在手机的多个屏幕上,因为没有足够的空间容纳所有碎片。