Emmachen / SapUi5Test

1 stars 1 forks source link

深入理解Android之AOP #38

Open ghost opened 8 years ago

ghost commented 8 years ago

原文

一、闲谈AOP

大家都知道OOP,即ObjectOriented Programming,面向对象编程。而本文要介绍的是AOP。AOP是Aspect Oriented Programming的缩写,中译文为面向切向编程。OOP和AOP是什么关系呢?首先: l OOP和AOP都是方法论。我记得在刚学习C++的时候,最难学的并不是C++的语法,而是C++所代表的那种看问题的方法,即OOP。同样,今天在AOP中,我发现其难度并不在利用AOP干活,而是从AOP的角度来看待问题,设计解决方法。这就是为什么我特意强调AOP是一种方法论的原因! l 在OOP的世界中,问题或者功能都被划分到一个一个的模块里边。每个模块专心干自己的事情,模块之间通过设计好的接口交互。从图示来看,OOP世界中,最常见的表示比如: clipboard1

图1中所示为AndroidFramework中的模块。OOP世界中,大家画的模块图基本上是这样的,每个功能都放在一个模块里。非常好理解,而且确实简化了我们所处理问题的难度。 OOP的精髓是把功能或问题模块化,每个模块处理自己的家务事。但在现实世界中,并不是所有问题都能完美得划分到模块中。举个最简单而又常见的例子:现在想为每个模块加上日志功能,要求模块运行时候能输出日志。在不知道AOP的情况下,一般的处理都是:先设计一个日志输出模块,这个模块提供日志输出API,比如Android中的Log类。然后,其他模块需要输出日志的时候调用Log类的几个函数,比如e(TAG,...),w(TAG,...),d(TAG,...),i(TAG,...)等。 在没有接触AOP之前,包括我在内,想到的解决方案就是上面这样的。但是,从OOP角度看,除了日志模块本身,其他模块的家务事绝大部分情况下应该都不会包含日志输出功能。什么意思?以ActivityManagerService为例,你能说它的家务事里包含日志输出吗?显然,ActivityManagerService的功能点中不包含输出日志这一项。但实际上,软件中的众多模块确实又需要打印日志。这个日志输出功能,从整体来看,都是一个面上的。而这个面的范围,就不局限在单个模块里了,而是横跨多个模块。 l 在没有AOP之前,各个模块要打印日志,就是自己处理。反正日志模块的那几个API都已经写好了,你在其他模块的任何地方,任何时候都可以调用。功能是得到了满足,但是好像没有Oriented的感觉了。是的,随意加日志输出功能,使得其他模块的代码和日志模块耦合非常紧密。而且,将来要是日志模块修改了API,则使用它们的地方都得改。这种搞法,一点也不酷。 AOP的目标就是解决上面提到的不cool的问题。在AOP中: l 第一,我们要认识到OOP世界中,有些功能是横跨并嵌入众多模块里的,比如打印日志,比如统计某个模块中某些函数的执行时间等。这些功能在各个模块里分散得很厉害,可能到处都能见到。 l 第二,AOP的目标是把这些功能集中起来,放到一个统一的地方来控制和管理。如果说,OOP如果是把问题划分到单个模块的话,那么AOP就是把涉及到众多模块的某一类问题进行统一管理。比如我们可以设计两个Aspects,一个是管理某个软件中所有模块的日志输出的功能,另外一个是管理该软件中一些特殊函数调用的权限检查。 讲了这么多,还是先来看个例子。在这个例子中,我们要: l Activity的生命周期的几个函数运行时,要输出日志。 l 几个重要函数调用的时候,要检查有没有权限。 注意,本文的例子代码在https://code.csdn.net/Innost/androidaopdemo上。

二、没有AOP的例子

先来看没有AOP的情况下,代码怎么写。主要代码都在AopDemoActivity中 [-->AopDemoActivity.java]

public class AopDemoActivity extends Activity {
   private static final String TAG = "AopDemoActivity";
Œ  onCreate,onStart,onRestart,onPause,onResume,onStop,onDestory返回前,都输出一行日志
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.layout_main);
       Log.e(TAG,"onCreate");
    }
   protected void onStart() {
       super.onStart();
        Log.e(TAG, "onStart");
    }
   protected void onRestart() {
       super.onRestart();
        Log.e(TAG, "onRestart");
    }
    protectedvoid onResume() {
       super.onResume();
        Log.e(TAG, "onResume");
   checkPhoneState会检查app是否申明了android.permission.READ_PHONE_STATE权限
        checkPhoneState();
    }
   protected void onPause() {
       super.onPause();
        Log.e(TAG, "onPause");
    }
   protected void onStop() {
       super.onStop();
        Log.e(TAG, "onStop");
    }
   protected void onDestroy() {
       super.onDestroy();
        Log.e(TAG, "onDestroy");
    }
   private void checkPhoneState(){
       if(checkPermission("android.permission.READ_PHONE_STATE")== false){
           Log.e(TAG,"have no permission to read phone state");
           return;
        }
       Log.e(TAG,"Read Phone State succeed");
       return;
    }
   private boolean checkPermission(String permissionName){
       try{
           PackageManager pm = getPackageManager();
          //调用PackageMangaer的checkPermission函数,检查自己是否申明使用某权限
           int nret = pm.checkPermission(permissionName,getPackageName());
           return nret == PackageManager.PERMISSION_GRANTED;
        }......
    }
}

文章好长,更多细节看原文吧: http://blog.csdn.net/innost/article/details/49387395