Android2.x中使用Fragment的调查

  • Fragment介绍

Fragment是在android3.0中引入的,其功能和Activity基本相似,有自己的回调和生命周期,对于Fragment的理解我们可以解释为碎片或片段,这一点和DOM中的片段可以类比。

关于设计哲学、生命周期、事务管理、与Activity通信、ActionBar的使用,官方的文档给出了比较详细的说明,这里不做赘述了。

http://developer.android.com/guide/components/fragments.html

 

  • Fragment应用场景

根据目前调查的情况这里列出几点

 

  1. 避免太多的Activity切换损伤系统的性能,FragmentActivity更轻量化
  2. 为应用程序提供统一的UI(以更低的成本统一2.x到最新版本的UI
  3. 为大屏设备提供更好的用户体验(例如新闻阅读,标题列表和内容同时展现)
  • android2.x中使用Fragment
  • Google的解决方案:

GoogleAndroid2.x使用Fragment提供了支持,并提供了官方的类库,可以从SDK Manager中下载,SDK Manager中的位置为Extras > Android Support Library,下载后存放于android-sdks\extras\android\support\v4中。

一般情况下如果只使用Fragment的话,那么该库就够用了,但是如果我们想用ActionBar的话,这个支持类库的功能就不够了。

  • Actionbarsherlock的解决方案:

该方案是使用actionbarsherlock开源类库,该方案提供了FragmentActionBar的支持,其本身的Fragment支持采用的是Google解决方案的类库。具体的使用类似于GreenDroid,需要使用该方案的应用程序需要导入actionbarsherlock项目。

  • 项目实践:

本次调查因为涉及到ActionBar,所以主要的输出内容以actionbarsherlock作为基础。

  • 代码获取:

actionbarsherlock官方网站下载actionbarsherlock项目及demo

地址:https://github.com/JakeWharton/ActionBarSherlock/zipball/4.1.0

  • Eclipse中导入actionbarsherlock项目:

这里有几点需要注意:

1.因为ADT版本差异,官方网站提供的导入步骤在较高版本的ADT中导入失败,这里采用的方法新建Android项目,然后将actionbarsherlocklibrary目录作为项目源码拷贝到新建项目的根目录下面,

2.actionbarsherlock中有的内容不好打包,只能通过项目引用的方式来工作。

3.编译环境的AndroidSDK版本必须在3.2以后,即project.properties中的target必须大于等于13,但工作换进可以是2.x

  • 项目引用:

我们的项目如果需要引用该库,需要这样引入:

右键 > properties > Android > library > Add > actionbarsherlock项目

不是这样:右键 > Build Path > Config Build Path > Project > Add > actionbarsherlock项目

  • 使用:

ActionBar使用:

 

   
   
   
   
  1. public class MainActivity extends BaseActivity{ 
  2.  
  3. private final static String TAB1 = "home"
  4.  
  5. private final static String TAB2 = "live"
  6.  
  7. private final static String TAB3 = "column"
  8.  
  9. private final static String TAB4 = "news"
  10.  
  11. private final static String TAB5 = "setting"
  12.  
  13. int mStackLevel = 1
  14.  
  15. HomeFragment homeFragment = new HomeFragment(); 
  16.  
  17. LiveFragment liveFragment = new LiveFragment(); 
  18.  
  19. ColumnFragment columnFragment = new ColumnFragment(); 
  20.  
  21. NewsFragment newsFragment = new NewsFragment(); 
  22.  
  23. SettingFragment settingFragment = new SettingFragment(); 
  24.  
  25. …………………………… 
  26.  
  27. protected void onCreate(Bundle savedInstanceState) { 
  28.  
  29. super.onCreate(savedInstanceState); 
  30.  
  31. setContentView(R.layout.fragment_stack); 
  32.  
  33. final ActionBar bar = getSupportActionBar() ; 
  34.  
  35.         bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
  36.  
  37.         bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); 
  38.  
  39.         bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_home_bg) 
  40.  
  41.                 .setText(R.string.tab_label_home) 
  42.  
  43.                 .setTabListener(new TabListener(homeFragment,TAB1))); 
  44.  
  45.         bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_live_bg) 
  46.  
  47.                 .setText(R.string.tab_label_live) 
  48.  
  49.                 .setTabListener(new TabListener(liveFragment,TAB2))); 
  50.  
  51.         bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_column_bg) 
  52.  
  53.             .setText(R.string.tab_label_column) 
  54.  
  55.                 .setTabListener(new TabListener(columnFragment,TAB3))); 
  56.  
  57.         bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_news_bg) 
  58.  
  59.             .setText(R.string.tab_label_news) 
  60.  
  61.                 .setTabListener(new TabListener(newsFragment,TAB4))); 
  62.  
  63.         bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_setting_bg) 
  64.  
  65.             .setText(R.string.tab_label_setting) 
  66.  
  67.                 .setTabListener(new TabListener(settingFragment,TAB5))); 
  68.  
  69.         if (savedInstanceState != null) { 
  70.  
  71.             bar.setSelectedNavigationItem(savedInstanceState.getInt("tab"0)); 
  72.  
  73.         } 
  74.  
  75.  
  76. …………………… 
  77.  

说明:

  1. 这里的ActionBar引用的是com.actionbarsherlock.app.ActionBar;
  2. 获取ActionBar需要使用getSupportActionBar()方法
  3. 这里的Fragment继承自android.support.v4.app.Fragment;
  4. bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);表示使用Tab    页形式展示。
  5. bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);显示标题栏。

Fragment使用:

   
   
   
   
  1. public class SettingFragment extends BaseFragment { 
  2.  
  3. int mNum; 
  4.  
  5. private Button share; 
  6.  
  7. private Button clear; 
  8.  
  9. private Button contact; 
  10.  
  11. /** 
  12.  
  13.  * 该方法用于Fragment默认构造 
  14.  
  15.  * @return  
  16.  
  17.  */ 
  18.  
  19. public SettingFragment(){ 
  20.  
  21.  
  22. public SettingFragment(int num){ 
  23.  
  24. this.mNum = num; 
  25.  
  26.  
  27. /** 
  28.  
  29.  * When creating, retrieve this instance's number from its arguments. 
  30.  
  31.  */ 
  32.  
  33. @Override 
  34.  
  35. public void onCreate(Bundle savedInstanceState) { 
  36.  
  37. Utils.log("onCreate"); 
  38.  
  39. super.onCreate(savedInstanceState); 
  40.  
  41. mNum = getArguments() != null ? getArguments().getInt("num") : 5
  42.  
  43.  
  44. /** 
  45.  
  46.  * The Fragment's UI is just a simple text view showing its instance number. 
  47.  
  48.  */ 
  49.  
  50. @Override 
  51.  
  52. public View onCreateView(LayoutInflater inflater, ViewGroup container, 
  53.  
  54. Bundle savedInstanceState) { 
  55.  
  56. Utils.log("onCreateView"); 
  57.  
  58. View v = inflater.inflate(R.layout.setting, container, false); 
  59.  
  60. getViews(v); 
  61.  
  62. setListener(); 
  63.  
  64. return v; 
  65.  
  66.  
  67. private void getViews(View container){ 
  68.  
  69. share = (Button)container.findViewById(R.id.setting_share_button); 
  70.  
  71. clear = (Button)container.findViewById(R.id.setting_clear_button); 
  72.  
  73. contact = (Button)container.findViewById(R.id.setting_contact_button); 
  74.  
  75.  
  76. private void setListener(){ 
  77.  
  78. share.setOnClickListener(new OnClickListener() { 
  79.  
  80. @Override 
  81.  
  82. public void onClick(View v) { 
  83.  
  84. startActivity(new Intent(getActivity(),ShareActivity.class)); 
  85.  
  86.  
  87. }); 
  88.  
  89. clear.setOnClickListener(new OnClickListener() { 
  90.  
  91. @Override 
  92.  
  93. public void onClick(View v) { 
  94.  
  95. startActivity(new Intent(getActivity(),ClearActivity.class)); 
  96.  
  97.  
  98. }); 
  99.  
  100. contact.setOnClickListener(new OnClickListener() { 
  101.  
  102. @Override 
  103.  
  104. public void onClick(View v) { 
  105.  
  106. startActivity(new Intent(getActivity(),ContactActivity.class)); 
  107.  
  108.  
  109. }); 
  110.  
  111.  



说明:
fragment第一次绘制它的用户界面的时候, 系统会调用此方法。为了绘制fragment的UI,此方法必须返回一个View, 这个view是你的fragment布局的根view。如果fragment不提供UI, 可以返回null。

  • 建议:

根据目前调查的情况,这里给出几点建议

  1. ActionBar的位置位于标题栏位置,而项目中的Tab标签位于屏幕底部,这里使用ActionBar可能会给用户点击带来一点小麻烦,可以考虑用户滑动屏幕自动切换Tab页。
  2. Fragment的主题以黑色为主,直接替换项目可能会有些地方色彩不协调,细节部分可能需要再设计一下
  3. Fragment框架需要引入主题,该主题会包含一个标题栏,替换之前的自定义标题栏还需要调查(这里是一个例子,更多的类容再向Fragment靠拢的开发中可能还会遇到)。
  • 结论:

项目向Fragment框架靠拢整理方案在技术上是可行的,并能因此提高系统的性能,但是在部分UI和用户体验上可能与之前的预期存在一点小差异,可能需要小修改。