【问题标题】:Android AOP/IOC applicatedAndroid AOP/IOC 应用
【发布时间】:2013-07-22 16:28:50
【问题描述】:

我最近在考虑应该如何以更好的方式完成

这是默认使用 Android SDK 的示例

public class MyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

这有点烦人,我们必须手动调用super.onCreate 否则应用程序会抛出异常

有没有什么办法可以更好地应用,通过注解或某种 AOP 钩子?

我想要

public class MyActivity extends Activity {

    @Override
    @OnCreate // Replaces super.onCreate call
    protected void onCreate(Bundle savedInstanceState) {

    }

}

甚至更好

public class MyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

    }

}

这可能吗?

【问题讨论】:

  • 不得不打电话给super 是你几乎无法解决的Java 问题。 github.com/roboguice/roboguice/wiki 但是通过注释简化了类似的事情。
  • @zapl 注解可以在某种代理父类中使用,所以这将是一个解决方案,您能否通过示例将其作为答案发布,如何应用它?

标签: java android inversion-of-control aop


【解决方案1】:

如果您想特别摆脱一些 super.theMethodIAmIn() 调用,实际上可以非常类似于“甚至更好”的情况,如果您在扩展的类中执行这些超级调用:

public class BetterActivity extends Activity {
    @Override
    protected final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        onCreateNoSuper(savedInstanceState);
    }
    // could be abstract as well.
    protected void onCreateNoSuper(Bundle savedInstanceState) {}
}

现在可以了

class MyActivity extends BetterActivity {
    @Override
    protected void onCreateNoSuper(Bundle savedInstanceState) {
        // done.
    }
}

缺点:

  • 您必须使用不同的方法名称。
  • 如果有人直接调用那些派生的 (onCreateNoSuper) 方法而不是调用 onCreate,语义上的细微变化可能会导致问题。 Android 的 onSomethingHappened 方法不应发生这种情况,因为只有系统调用它们。
  • 如果您再次扩展 MyActivity,则必须再次调用 super 或再次使用相同的技巧。

一个非常相似的方法应该通过注释工作。例如Android Annotations#HowItWorks 是在编译时通过Java 的注解处理器动态创建子类的示例。

例如,您可以像这样编写代码

class MySpecialActivity extends Activity {
    @OnCreate
    protected void randomlyNamed(Bundle savedInstanceState) {
        // done.
    }
}

注释处理器会生成

class MySpecialActivity_ extends MySpecialActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        randomlyNamed(savedInstanceState);
    }
}

这里的缺点:

  • 您需要编写相当复杂的代码来动态生成.java 文件。
  • 您需要配置构建环境以运行注释处理器。
  • 您需要在多个地方使用生成的子类而不是您的类。
  • 你甚至没有保存一行代码,因为你用一些 @OnCreate 注释替换了超级调用。

更进一步,您可以通过修改编译的字节码将超级调用物理地插入方法中(参见例如ASM)。您仍然需要配置您的构建环境来执行该步骤,但现在您可以真正执行您在“更好”案例中编写的内容。像往常一样编写代码,如果你忘记了这些讨厌的调用,你的后编译器只会添加它们。

这也是 proguard 所做的。在 Android 的 dex 编译器将结果转换为 android 的 dex 格式之前,它会检查字节码、优化和混淆它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-17
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多