javaRegisterCode static method
Implementation
static String javaRegisterCode(Module module, UniAPIOptions options) {
return CodeTemplate(children: [
CommentUniAPI(),
EmptyLine(),
JavaPackage(module.inputFile, options),
EmptyLine(),
JavaImport(fullClassName: 'java.util.List'),
JavaImport(fullClassName: 'java.util.ArrayList'),
JavaImport(fullClassName: 'java.util.Map'),
JavaImport(fullClassName: 'java.util.HashMap'),
JavaImport(fullClassName: 'android.util.Log'),
JavaImport(fullClassName: 'io.flutter.plugin.common.BasicMessageChannel'),
JavaImport(fullClassName: 'io.flutter.plugin.common.BinaryMessenger'),
JavaImport(
fullClassName: 'io.flutter.plugin.common.StandardMessageCodec'),
JavaImport(
fullClassName:
'${options.javaPackageName}.${options.javaUniAPIPrefix}$kUniAPI'),
JavaImport(
fullClassName:
'static ${options.javaPackageName}.$projectName.UniModel.map'),
JavaCustomNestedImports(module.inputFile, options,
methods: module.methods, excludeImports: [typeUniCallback]),
EmptyLine(),
JavaClass(
className: '${module.name}Register',
isPublic: true,
injectedJavaCodes: (depth) => [
...JavaCollectionCloneFunction()
.handlerJavaCollectionType(methods: module.methods),
JavaFunction(
depth: depth,
functionName: 'setup',
isPublic: true,
params: [
Variable(
AstCustomType('BinaryMessenger'), 'binaryMessenger'),
Variable(AstCustomType(module.name), 'impl')
],
isStatic: true,
body: (depth) => module.methods
.where((method) => method.name != module.name)
.map((method) => ScopeBlock(
depth: depth + 1,
body: (depth) => [
OneLine(
depth: depth,
body:
'BasicMessageChannel<Object> channel ='),
OneLine(
depth: depth + 2,
body:
'new BasicMessageChannel<>(binaryMessenger, "${_getModuleRegisterChannelName(module, method)}", new StandardMessageCodec());'),
IfBlock(
OneLine(
body: 'impl != null',
hasNewline: false), (depth) {
final ret = <CodeUnit>[];
ret.add(OneLine(
depth: depth,
body:
'${options.javaUniAPIPrefix}$kUniAPI.registerModule(impl);'));
ret.add(OneLine(
depth: depth,
body:
'channel.setMessageHandler((message, reply) -> {'));
ret.add(OneLine(
depth: depth + 1,
body:
'Map<String, Object> wrapped = new HashMap<>();'));
ret.add(OneLine(
depth: depth + 1, body: 'try {'));
ret.add(OneLine(
depth: depth + 2,
body:
'Map<String, Object> params = (Map<String, Object>) message;'));
// 将 Channel 调用传过来的数据转换成方法调用参数
// 常规参数解析
for (final param in method.parameters) {
if (param.type.astType() ==
typeUniCallback) {
// 这里第二个参数,取出的是对应 Callback 的唯一名称,这个从 Native 带到 Dart 再带回来
final callbackClassName =
'${module.name}.${JavaClassUniCallback.getName(method.name, param.name)}';
ret.add(OneLine(
depth: depth + 2,
body:
'$callbackClassName ${param.name} = new ${module.name}.${JavaClassUniCallback.getName(method.name, param.name)}(binaryMessenger, (String) params.get("${param.name}"));'));
} else {
final decoded = param.type
.convertJavaJson2Obj(
vname:
'params.get("${param.name}")');
ret.add(OneLine(
depth: depth + 2,
body:
'${param.type.javaType()} ${param.name} = params.containsKey("${param.name}") ? $decoded;'));
}
}
// 生成实际方法调用
var paramsList = method.parameters
.map((e) => e.name)
.toList()
.join(', ');
if (!method.isAsync) {
final call = OneLine(
depth: depth + 2,
body:
'impl.${method.name}($paramsList);');
if (method.returnType is AstVoid) {
ret.add(call);
} else {
ret.add(OneLine(
depth: depth + 2,
body:
'${method.returnType.javaType()} output = ${OneLine(body: call.body).build().replaceAll('\n', '')}'));
}
final isCustomType = method.returnType
.realType() is AstCustomType;
// != null 表达式
final neqNullExp = isCustomType
? 'output != null ? '
: '';
// null 表达式
final nullExp =
isCustomType ? ' : null' : '';
ret.add(OneLine(
depth: depth + 2,
body:
'wrapped.put("${Keys.result}", $neqNullExp${method.returnType.realType().convertJavaObj2Json('output')}$nullExp);'));
} else {
final retValue = method.returnType
.realType()
.convertJavaObj2Json('ret');
paramsList +=
'${paramsList.isNotEmpty ? ', ' : ''}(ret) -> {';
ret.add(OneLine(
depth: depth + 2,
body:
'impl.${method.name}($paramsList'));
//构造 try{} catch{}
ret.add(OneLine(
depth: depth + 3, body: 'try {'));
ret.add(OneLine(
depth: depth + 4,
body:
'wrapped.put("result", $retValue);'));
ret.add(OneLine(
depth: depth + 4,
body: 'reply.reply(wrapped);'));
ret.addAll(_buildJavaCatchErrorTemplate(
isAsync: method.isAsync,
ignoreError: method.ignoreError,
baseDepth: depth + 2));
}
ret.addAll(_buildJavaCatchErrorTemplate(
isAsync: method.isAsync,
ignoreError: method.ignoreError,
baseDepth: depth));
return ret;
},
elseContent: (depth) => [
OneLine(
depth: depth,
body:
'channel.setMessageHandler((message, reply) -> {});')
],
depth: depth)
]))
.toList()),
EmptyLine(),
JavaFunction(
depth: depth,
functionName: 'wrapError',
isPrivate: true,
isStatic: true,
params: [Variable(AstCustomType('Throwable'), 'exception')],
returnType: AstMap(keyType: AstString()),
body: (depth) => [
OneLine(
depth: depth + 1,
body:
'Map<String, Object> errorMap = new HashMap<>();'),
OneLine(
depth: depth + 1,
body:
'errorMap.put("message", exception.toString());'),
OneLine(
depth: depth + 1,
body:
'errorMap.put("code", exception.getClass().getSimpleName());'),
OneLine(
depth: depth + 1,
body: 'errorMap.put("details", null);'),
OneLine(depth: depth + 1, body: 'return errorMap;'),
])
])
]).build();
}