有一种更好的方法称为 AOP(面向方面编程)。过去(大约 7 年前)我在 C# 中使用 SpringFramework 和 PostSharp 有过一些经验。这种方法广泛使用代码注入技术。
所以当我遇到这个问题(跟踪 GL 错误)时,它似乎是 AOP 的一个经典问题。由于代码注入会带来一些性能损失,因此我假设此更改(启用 GL 日志记录)是暂时的,并将在我想要使用它的情况下将其保存在 git 补丁中。
1)首先,更改您的 gradle 构建脚本:在顶级构建脚本中添加:
buildscript {
dependencies {
classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.14'
在应用程序级脚本中添加:
apply plugin: 'com.uphyca.android-aspectj'
这将在 gradle 中启用 aspectj 插件。这个项目(托管在这里:https ://github.com/uPhyca/gradle-android-aspectj-plugin )现在似乎已被弃用,但它正在工作。您可以在这里查看更新的版本:https ://github.com/HujiangTechnology/gradle_plugin_android_aspectjx 。对于我的需要(基本的 java 代码编织),旧版本运行良好。重建以查找是否有任何问题。
2)添加我们稍后将使用的注释来标记我们希望将方面应用于的方法:
package com.example.neutrino.maze;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by Greg Stein on 7/18/2016.
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface GlTrace {
}
3)添加我们的方面:
package com.example.neutrino.maze;
import android.opengl.GLES20;
import android.opengl.GLU;
import android.util.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
/**
* Created by Greg Stein on 7/18/2016.
*/
@Aspect
public class GlTraceAspect {
private static final String POINTCUT_METHOD =
"execution(@com.example.neutrino.maze.GlTrace * *(..))";
private static final String POINTCUT_CONSTRUCTOR =
"execution(@com.example.neutrino.maze.GlTrace *.new(..))";
@Pointcut(POINTCUT_METHOD)
public void methodAnnotatedWithGlTrace() {}
@Pointcut(POINTCUT_CONSTRUCTOR)
public void constructorAnnotatedWithGlTrace() {}
@Around("methodAnnotatedWithGlTrace() || constructorAnnotatedWithGlTrace()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
Signature signature = joinPoint.getSignature();
String className = signature.getDeclaringType().getSimpleName();
String methodName = signature.getName();
// Before method execution
// -- nothing --
Object result = joinPoint.proceed();
// After method execution
Log.d(className, buildLogMessage(methodName));
return result;
}
/**
* Create a log message.
*
* @param methodName A string with the method name.
* @return A string representing message.
*/
private static String buildLogMessage(String methodName) {
StringBuilder message = new StringBuilder();
int errorCode = GLES20.glGetError();
message.append("GlState[");
message.append(methodName);
message.append("]: ");
if (GLES20.GL_NO_ERROR != errorCode) {
message.append("ERROR:");
}
message.append(GLU.gluErrorString(errorCode));
return message.toString();
}
}
4)用@GlTrace注解标记执行GL代码的方法或构造函数:
...
@GlTrace
public GlEngine(int quadsNum) {
...
@GlTrace
public void draw(float[] mvpMatrix) {
...
现在完成所有这些之后,只需在 AndroidStudio 中重新运行该项目。您将获得以下输出:
07-18 12:34:37.715 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[<init>]: no error
07-18 12:34:37.715 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[draw]: no error
07-18 12:34:37.733 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[<init>]: no error
07-18 12:34:37.735 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[draw]: no error
07-18 12:34:37.751 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[<init>]: no error
07-18 12:34:37.751 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[draw]: no error
07-18 12:34:37.771 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[<init>]: no error
07-18 12:34:37.771 19167-19187/com.example.neutrino.maze D/GlEngine: GlState[draw]: no error
在我的项目中,我只有两个带有 GL 调用的方法:draw 方法和 GlEngine 类的构造函数。
在您使用它并获得那些烦人的“无错误”消息后,您可以进行一些改进: 0)仅打印错误 1)监视与 gl* 匹配的所有方法(所有 OpenGL 方法)。
享受!