设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Android中提取表单模型

2014-7-10 11:35| 发布者: joejoe0332| 查看: 4532| 评论: 0|原作者: lum|来自: 伯乐在线

摘要:   我一直追求从Android活动中分离代码。在最近的一个项目中,我成功的实现了传统的”Form Model”模式,想在此分享我的感想。  “Form Model”的基本思想是,把处理UI交互以及数据绑定和状态保持的代码提取到单 ...


  我们把Android控件封装到getter和setter方法中​——这可能会有些争议,但我认为它使SearchForm拥有更好的公共API。我们有一个方法来验证用户的输入,并根据需要提供错误信息。buildParameters()方法做了一些数据绑定工作并返回业务对象。结尾的两个方法使用了AndroidonSaveInstanceState中的Bundle,以处理自定义配置的更改(注意,大多数的原始UI控件会自行处理持久化)。


  这是个一百行左右的代码,大部分还不错。这个类中所有内容似乎都属于“搜索表单”对象,对未来的特性有良好的功能扩展点(日期范围过滤器、支出与存款过滤器、只用支票等)。我们有意避免处理如何获取数据,把它留给了其他更适合的地方处理这些逻辑代码。


  活动中的代码是什么样的呢?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class TransactionSearchActivity extends BaseActivity {
 
  @InjectView(R.id.search_form)
  private SearchForm mForm;
 
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.transaction_search);
    setTitle("Search Your Transactions");
 
    mForm.initialize(mAccounts); // fetch accounts via API/DB/etc
 
    if (savedInstanceState != null) {
      mForm.restore(savedInstanceState);
    }
  }
 
  @Override
  public boolean onOptionsItemSelected(MenuItem menu) {
    switch (menu.getItemId()) {
      case R.id.action_submit_search:
        onSubmitSearch();
        return true;
    }
 
    return super.onOptionsItemSelected(menu)
  }
 
  private void onSubmitSearch() {
    if (mForm.validate()) {
      // Do your magic, post to an API/DB/etc
      // You have access to the domain object with mForm.buildParameters()
    }
  }
 
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_menu, menu);
    return super.onCreateOptionsMenu(menu);
  }
 
  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
 
    mForm.persist(outState);
  }
}


  我们的Activity在XML布局文件中包含了一个 **标签,并且只处理高层面的用户交互(点击动作栏中的提交按钮),并协调获取和存储数据。繁重的UI控制和表单逻辑都委托给了 **SearchForm


  Activity的代码在50行左右——其中大部分是处理框架中生命周期和菜单创建的样板代码。


总体印象


  一旦涉及到API或数据库,事情总是会变得更复杂。但总体来讲,通过把表单特定的逻辑和视图相关内容移出活动,代码变得更容易理解。


  我可以为 SearchForm编写大量的Robolectric测试代码而且不会带来与活动生命周期有关的问题。我可以为表单的交互、动作栏、后端编写测试代码而不用考虑边界。当为表单添加新过滤条件时,可以避免对活动做任何的更改(类似于设计模式中的开/闭原则)。


  对比其他框架(从其他开发人员的角度来说),Android中数据绑定功能很弱。这种设计似乎还差点什么,因为和Android的类耦合的过于紧密,依赖于方法的调用顺序(initialize()方法应在validate()方法之前调用)——尽管如此,但我认为对于“所有内容混在一起的Activity”来说是一种改进。


  随着表单模型越来越复杂,你可能要考虑把验证逻辑提取到一个单独的对象中,并且把自定义视图功能移动到自己的控件中(就像我们例子中的 CurrencyEditText)。此外,为了更好的为用户服务,也可以考虑把复杂的表单拆分成为多步骤向导。


  我们发现这种模式可以成功的清理乱糟糟的表单代码,建议尝试一下。我把代码模式稍微规范了一下,并创建了一个小的基类,以减少样板代码,可以随意的使用



  我希望听到您的想法、意见或建议,请在Twitter上和我联系。


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部