自定义编译时注解框架完善Android模块间通信参数获取过程

本文介绍了一种编译时注解框架的设计与实现,该框架简化了Android应用中模块间通信参数的获取过程。文章详细展示了注解、注解处理器及API的编写,并提供了具体使用案例。

这里为了加深对编译时注解框架的使用同时为了完善之前Android模块间通信参数的获取过程,决定自己写一个简单的编译时注解框架,主要是替代

getIntent().getExtras().getSerializable

获取参数代码的编写。感兴趣的朋友可以先浏览之前的Android模块化学习Android编译时注解项目学习。详细代码路径点这里

回顾一下编译时注解框架的大致流程:

(1)编写注解代码

(2)编写注解处理器,用于生成java文件实现getIntent的获取过程

(3)编写API用于调用注解处理器生成的java文件

在我看来,编译时注解框架的核心在于处理一些重复的代码,解放我们的时间,所以最重要在于如何生成java文件来实现上面的getIntent过程,而其余的代码其实只要套用模板即可。

一、编写注解

(1)新建了一个ioc-annotation模块,同时增加了BindParameter这个注解,具体代码如下:

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindParameter {
    String value();
}

这个注解代码很简单,就设置了作用域和注解类型

二、编写注解处理器

(1)新建ioc-compiler模块,这个模块必须是java模块,否则一些方法无法调用

(2)只实现具体生成的java代码,其他皆可套用模板来开发。

public String generateJavaCode()
    {
        StringBuilder builder = new StringBuilder();
        builder.append("// Generated code. Do not modify!\n");
        builder.append("package ").append(packageName).append(";\n\n");
        builder.append("import com.example.francis.bmodule.*;\n");
        builder.append("import com.example.francis.commonmodule.inject.ParameterInject;\n");
        builder.append('\n');

        builder.append("public class ").append(proxyClassName).append(" implements " + ParameterProxyInfo.PROXY + "<" + typeElement.getQualifiedName() + ">");
        builder.append(" {\n");

        generateMethods(builder);
        builder.append('\n');

        builder.append("}\n");
        return builder.toString();

    }
    private void generateMethods(StringBuilder builder)
    {

        builder.append("@Override\n ");
        builder.append("public void inject(" + typeElement.getQualifiedName() + " host) {\n");

        for (String id : injectVariables.keySet())
        {
            VariableElement element = injectVariables.get(id);
            String name = element.getSimpleName().toString();
            String type = element.asType().toString();
            builder.append("if(host.getIntent() != null){\n");
            builder.append("host." + name).append(" = ");
            builder.append("(" + type + ")(host.getIntent().getExtras().getSerializable( \"" + id + "\"));\n");
            builder.append("}\n");
        }
        builder.append("  }\n");

    }

我觉得可以这样调试,这块代码不一定要一次性就写对,毕竟没有真正的运行过,可以等build项目生成具体java文件后再修改,如果有报错,编译器会直接提示,通过修改编译后的java文件在反过来修改这里的方法,也更直观有效。编译后生成的代码如下:

package com.example.francis.bmodule;

import com.example.francis.bmodule.*;
import com.example.francis.commonmodule.inject.ParameterInject;

public class BmoduleMainActivity$$ParameterInject implements ParameterInject<com.example.francis.bmodule.BmoduleMainActivity> {
@Override
 public void inject(com.example.francis.bmodule.BmoduleMainActivity host) {
if(host.getIntent() != null){
host.user = (com.example.francis.commonmodule.User)(host.getIntent().getExtras().getSerializable( "user"));
}
  }

}

三、编写API

编写API的代码也是套用模板,直接使用即可,它的原理在于调用刚才生成的Java文件实现具体的赋值。代码这里就不再贴出来,详细可以直接查看上面提供的项目demo。

四、具体使用

(1)在使用项目中添加依赖,包括注解,api和注解处理器模块的依赖

implementation project(':commonModule')
    implementation project(':ioc-annotation')

    annotationProcessor project(':ioc-compiler')

(2)代码中使用注解并调用API接口

public class BmoduleMainActivity extends AppCompatActivity {

    @BindParameter("user")
    User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bmodule_main);
        ParameterInjector.injectParameter(this);

        Toast.makeText(this, "user: " + user.getName() + " age: " + user.getAge(), Toast.LENGTH_LONG).show();


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值