我们知道程序的可用性或者说健壮性非常重要,如果在用户使用的过程中,出现了程序崩溃,或者数据错误都是灾难性的。
为了最小化出错的概率,我们想各种办法来减错、容错、纠错。不管怎么减错,比如说提高代码质量、测试驱动开发、大量测试等等,但仍不可避免,还是有各式各样的错误出现。尤其是有UI,需要用户参与的话,错误会更多,因为你不知道用户到底是怎么使用应用程序的。所以容错不可避免!
在Java中,错误有两种类型,Error和Exception。我们能处理的主要是Exception。如果要容错,首先需要把错误限定到一定范围,捕获异常,更重要的是要保证数据的完整性。比如说,一个动作任务会有多个小任务,进行了一半,发生了异常。怎么办?这时,如果捕获了异常,但还不够,动作停留在中间位置,这是一个错误的状态,需要跳转到正确的状态。 怎么实现?这就是我们今天所讲的特性-本地事务所干的事。
例子地址在这里。
1, 首先, 需要在感受方法上添加注解@Transacational
/* * 感受方法,监听GridView中所有的按钮。 */ @Recept(target="grid.*", stimulation="android.view.View$OnClickListener") @Transactional("input") private void onItemClick(TextView view) { String text = view.getText().toString(); stringInputCenter.input(text); if(text.equals(StringConstant.Exception)) { int[] a = null; System.out.println(a.length); //发生异常 } }
这样,该方法 就被本地事务给管理了,当方法内部发生了异常 ,则异常自动捕获 ,并且数据默认发生回滚。
2, 如果你需要自己处理异常,则可以实现IRollbackThrowableAware接口。
@Receptor public class StringInputReceptor implements IRollbackThrowableAware{ { ... //其他省略 @Override public boolean onRollbackThrowable(final TransactionManager transactionManager, String transactionName, Throwable throwable) { stringInputCenter.info("在事务:" + transactionName + "中捕获到异常: " + throwable.getMessage()); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { private int count = 5; @Override public void run() { stringInputCenter.info("准备回滚,倒计时: " + count); if(count == 0) { transactionManager.rollback(); stringInputCenter.info("回滚成功!"); stringInputCenter.refresh(); } else { handler.postDelayed(this, 1000); } count --; } }, 2000); return true; } }
在该例中,是这样处理异常的。首先提示用户发生了异常,然后倒计时回滚 ,以便用户有反应时间。
是不是很简单?
需要注意的是,本地事务回滚是基于数据的,这样的话有两个问题:
- 数据类型需要是特殊类型。这个很多人不高兴了,还是喜欢Java原生的。但其实无所谓,习惯就好,也没有增加多少工作量,为了程序稳定,为了用户,只能忍忍了,谁让顾客就是上帝呢。还有就是数据目前只支持Value<T> 类型,T是List和Map以外所有类型。至于List和Map,下一步会加上。
- 对于视图开发,需要数据驱动。但是很多GUI框架不是这样设计的,这也是Reflex需要去适配的地方。
PS. Reflex框架地址
时间: 2024-11-05 00:45:59