猫左羽右

合理设计为Android程序引入“关闭程序”机制

羽毛 发表于: 五月 11th, 2011 | 阅读: 1,281 views | 评论数: (7)

做Android开发的同学们大概都曾抱怨过Android的程序退出机制——就是没有退出机制。因此今天羽毛想跟大家分享下羽毛在这方面的编程技巧。<因本文存在许多极可能与事实不符的内容,不推荐大家使用其中机制。对该问题的更多探讨将在下一篇文章中讨论>

目前在网上流传的解决方案主要有两类(三种),在正式引入羽毛的方法之前,我们先讨论下已有的方法:(可以参考这里,这个排版不错

第一类(参考文的前两种方法):调用系统API直接结束进程,即调用“killProcess”或者“System.exit”。首先我在实验时,这两种方法根本不能工作,我是在Android2.2/2.3.3上做的实验,如果有谁在某个版本上实验成功,请通知我!还有一种也是类似的,并且需要权限android.permission.RESTART_PACKAGES,我没有去测试这个方法能否成功,因为我觉得如果一个程序都需要申请权限来退出,一定是非常不靠谱的事情。

第二类(参考文的第三种方法):这个解决方案已经比较接近羽毛的解决方式了,没有特别的坏处,只是这种每次调用Intent都清掉其他的Activity的方式不太灵活,而且整个代码的设计也不太好(通过一个Activity结束其他的Activity,有点破坏封装)。

所以,现在开始介绍羽毛自己的方案啦:

首先说,我的解决方案只是通过一些比较OO的巧妙设计来提供一个良好的退出机制,相当于自己封装了一个API,但是为了保证SDK的原始性,我并没有尝试把它hack进原生SDK中。另外这样的解决方案也绝不是“一键宏”,毕竟前文提到的“一键永逸”的方法也没有能工作的。

那么就来说说思路:Android变态的原生退出机制其实是当所有的Activity都finish以后,它的主程序就退出了(并不影响后台service)。而不知道什么原因,它没有提供直接退出的API。另外,在Android中,一个比较糟糕的设计,就是“返回键”的原生作用——从Activity的历史栈中将下一个Activity调出来。如果我们任由这样的返回键胡乱非为,就很可能打乱整个程序的业务逻辑——返回到过期页面。因此我们整个解决方案分为两部分:1、提供对所有打开的Activity的管理机制;2、重定义返回键的用途。

一、Activity管理机制:

考虑到这是一个全局的行为,因此我强烈建议大家在封装这个功能类的时候采用单态模式。具体做法是先设计一个功能类(单态的),在其中管理一个Activity的List,然后通过Add和Remove方法增删Activity,另外再提供一个Close方法结束所有的Activity。相信这么一说,大家都明白了吧,那么给出示例:

然而由于这并不是一项必不可少的行为,因此在初次使用过程中,很容易忘记调用这些API。那么接下来是讨论在哪里使用这些方法,很简单,在所有继承了Activity的类中,重载onCreate和onDestroy方法,并且在其中分别调用CloseMe的Add和Remove方法,这样的好处是你不需要在一个类中多次插入这些代码,以至于因为你的遗忘而漏管理了某个Activity,特别的,你在任何地方调用一个类的finish方法都可以通过onDestroy方法将该类从链表中删除。

二、重定义返回键的用途:

由于非常不满Android原生对返回键的定义,因此我几乎会在所有的Activity中劫持按键,然后重新分配返回键的定义。劫持按键的方法就是在有继承Activity的类中重载“dispatchKeyEvent”方法。下面先给出我其中一个比较完整的例子,然后再继续讨论。

首先屏蔽返回键,或者为返回键引入新的方法,都可以有效防止用户返回到过期的页面。另外说两个细节:

1、首先看第一个IF判断句,我之所以要特别地注明是在“Action Up”的时候,是因为如果不注明,那么返回键在被按下和弹起时,会响应两次事件,这样也会带来很多麻烦。

2、一开始我是没有第二条IF句的,大家可以先把第二个IF句注释掉,然后观察这段代码,会发现极有可能你该Activity页面中的EditText中的内容无法删除,后来我发现,是因为如果不掉用父类的dispatchKeyEvent方法,原始的DELETE键也失去了原有意义(奇怪的是其他的普通键却不会),因此我特别地引入了这条判断。

——————————————————-

好了,现在就介绍完这些小技巧了。希望对大家能有帮助。

Tags: , , ,

7 枚回复


  1. Mi 说道:

    好了,现在就知道这儿有这篇文章了,希望什么时候能用上。

  2. Mi 说道:

    看来你热的退化了,就是说我没看懂,啥时候看得懂了再看看

  3. 上官博微 说道:

    我说哥们,你说的很好,不过,如果我想要在某个点击事件中实现这个功能的话,要该怎么办啊?并且在上述函数中出现过endMe(),他好像不是java或者android内部封装的函数

    • 羽毛 说道:

      我希望你有看我的另一篇文章《再谈安卓应用程序退出机制》:http://www.mielf.net/featherelf/%E5%86%8D%E8%B0%88%E5%AE%89%E5%8D%93%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E9%80%80%E5%87%BA%E6%9C%BA%E5%88%B6
      这里有更正确的关于退出机制的描述。

    • 羽毛 说道:

      另外,endMe()是我自己的函数。


发表回复