Browse Source

add lifecycle agent

weiguo 7 years ago
parent
commit
821b6d4fd0

+ 6 - 10
app/src/main/java/com/uddream/plugin/MainActivity.java

@@ -13,8 +13,6 @@ import com.uddream.library.Test;
 
 public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
 
-//    LifeCycleDelegate $lifeCycleAresDelegate;
-
     private View.OnClickListener listener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
@@ -25,7 +23,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
         setContentView(R.layout.activity_main);
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
@@ -35,6 +32,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
         fab.setOnClickListener(new Test());
         fab.setOnClickListener(this);
         new CheckBox(this).setOnCheckedChangeListener(this);
+
     }
 
     @Override
@@ -43,6 +41,11 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
     public void onClick(View v) {
         System.out.print("onClick listener");
     }
@@ -51,11 +54,4 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
     public void onCheckedChanged(CompoundButton v, boolean isChecked) {
         System.out.print("onCheckedChanged listener");
     }
-
-//    public LifeCycleDelegate $getLifeCycleAresDelegate() {
-//        if ($lifeCycleAresDelegate == null) {
-//            $lifeCycleAresDelegate = LifeCycleDelegate.create(this);
-//        }
-//        return $lifeCycleAresDelegate;
-//    }
 }

+ 4 - 4
buildSrc/src/main/groovy/com/gradle/ares/ClassAdapter.groovy

@@ -17,7 +17,7 @@ public class ClassAdapter extends ClassVisitor {
     private Logger logger;
 
     private boolean modify;
-    private int access;
+    private String name;
     private String superName;
     private String[] interfaces;
 
@@ -32,7 +32,7 @@ public class ClassAdapter extends ClassVisitor {
     @Override
     public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
         super.visit(version, access, name, signature, superName, interfaces)
-        this.access = access
+        this.name = name
         this.superName = superName
         this.interfaces = interfaces
         debug("class:" + name + "_" + superName + "_" + interfaces)
@@ -55,7 +55,7 @@ public class ClassAdapter extends ClassVisitor {
             addAgents.add(agent)
 
             modify = true
-            mv = new MethodLifeCycleVisitor(mv, agent)
+            mv = new MethodLifeCycleVisitor(mv, name, agent)
         }
         return mv
     }
@@ -68,7 +68,7 @@ public class ClassAdapter extends ClassVisitor {
     @Override
     void visitEnd() {
         if (addAgents != null) {
-            MethodLifeCycleVisitor.addMethods(addAgents, this.cv)
+            MethodLifeCycleVisitor.addMethods(addAgents, name, superName, this.cv)
         }
         super.visitEnd()
     }

+ 4 - 5
buildSrc/src/main/groovy/com/gradle/ares/MethodAgentVisitor.groovy

@@ -2,13 +2,12 @@ package com.gradle.ares
 
 import org.objectweb.asm.MethodVisitor
 import org.objectweb.asm.Opcodes
-import org.objectweb.asm.commons.GeneratorAdapter
 
 /**
  * Created by Glen on 2017/2/8.
  */
 
-public class MethodAgentVisitor extends GeneratorAdapter {
+public class MethodAgentVisitor extends MethodVisitor {
     public final static String AgentClass = "com/uddream/plugin/Agent";
 
     public final static Agent[] Modify = [
@@ -30,7 +29,7 @@ public class MethodAgentVisitor extends GeneratorAdapter {
     private Agent agent;
 
     MethodAgentVisitor(MethodVisitor mv, Agent agent) {
-        super(Opcodes.ASM5, mv, agent.access, agent.name, agent.desc)
+        super(Opcodes.ASM5, mv)
         this.agent = agent
         for (def item : agent.desc.substring(1, agent.desc.indexOf(")")).split(";")) {
             if (!item.equals("")) this.pCount++
@@ -40,14 +39,14 @@ public class MethodAgentVisitor extends GeneratorAdapter {
     @Override
     void visitCode() {
         super.visitCode()
-        for (int i = 0; i < pCount; i++) loadArg(i)
+        for (int i = 1; i <= pCount; i++) visitVarInsn(Opcodes.ALOAD, i)
         visitMethodInsn(Opcodes.INVOKESTATIC, AgentClass, agent.name + "Pre", agent.desc, false)
     }
 
     @Override
     public void visitInsn(int opcode) {
         if (opcode == Opcodes.RETURN) {
-            for (int i = 0; i < pCount; i++) loadArg(i)
+            for (int i = 1; i <= pCount; i++) visitVarInsn(Opcodes.ALOAD, i)
             visitMethodInsn(Opcodes.INVOKESTATIC, AgentClass, agent.name, agent.desc, false)
         }
         super.visitInsn(opcode);

+ 57 - 24
buildSrc/src/main/groovy/com/gradle/ares/MethodLifeCycleVisitor.groovy

@@ -1,18 +1,19 @@
 package com.gradle.ares
 
+import org.gradle.api.logging.Logging
 import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.FieldVisitor
 import org.objectweb.asm.Label
 import org.objectweb.asm.MethodVisitor
 import org.objectweb.asm.Opcodes
-import org.objectweb.asm.commons.GeneratorAdapter
 
 /**
  * Created by Glen on 2017/2/8.
  */
 
-public class MethodLifeCycleVisitor extends GeneratorAdapter {
+public class MethodLifeCycleVisitor extends MethodVisitor {
     public final static String LifeClass = "com/uddream/plugin/LifeCycleDelegate";
+    public final static String GetLifeMethod = "\$getLifeCycleAresDelegate";
 
     public final static String[] SuperClass = [
             "android/app/Activity",
@@ -27,7 +28,6 @@ public class MethodLifeCycleVisitor extends GeneratorAdapter {
     ] as String[]
 
     public final static Agent[] Modify = [
-            new Agent("\$getLifeCycleAresDelegate", "()L" + LifeClass + ";"),
             new Agent("onCreate", "(Landroid/os/Bundle;)V"),
             new Agent("onResume", "()V"),
             new Agent("onPause", "()V"),
@@ -53,32 +53,72 @@ public class MethodLifeCycleVisitor extends GeneratorAdapter {
         return null
     }
 
-    public final static void addMethods(Set<Agent> agentSet, ClassVisitor cv) {
-        cv.visitField(Opcodes.ACC_PUBLIC, "\$lifeCycleAresDelegate", "L" + MethodLifeCycleVisitor.LifeClass + ";", null, null)
-        MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "\$getLifeCycleAresDelegate", "()Lcom/uddream/plugin/LifeCycleDelegate;", null, null)
+    public final
+    static void addMethods(Set<Agent> agentSet, String name, String superName, ClassVisitor cv) {
+        addLifeCycleFieldMethod(cv)
+        for (Agent agent : Modify) {
+            if (!agentSet.contains(agent)) {
+//                //method
+//                int count = 0;
+//                for (def item : agent.desc.substring(1, agent.desc.indexOf(")")).split(";")) {
+//                    if (!item.equals("")) count++
+//                }
+//
+//                MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, agent.name, agent.desc, null, null)
+//                mv.visitCode()
+//                mv.visitVarInsn(Opcodes.ALOAD, 0)
+//                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, name, GetLifeMethod, "()L" + LifeClass + ";", false)
+//                for (int i = 1; i <= count; i++) mv.visitVarInsn(Opcodes.ALOAD, i)
+//                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LifeClass, agent.name, agent.desc, false)
+//
+//                mv.visitVarInsn(Opcodes.ALOAD, 0)
+//                for (int i = 1; i <= count; i++) mv.visitVarInsn(Opcodes.ALOAD, i)
+//                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, agent.name, agent.desc, false)
+//                mv.visitInsn(Opcodes.RETURN)
+//                mv.visitMaxs(0, 0)
+//                mv.visitEnd()
+            }
+        }
+    }
+
+    /**
+     * 注入代理字段及初始化方法
+     * @param cv
+     */
+    private final static void addLifeCycleFieldMethod(ClassVisitor cv) {
+        //desc
+        String fieldName = "\$lifeCycleAresDelegate"
+        String fieldDesc = "L" + LifeClass + ";"
+        //field
+        FieldVisitor fv = cv.visitField(Opcodes.ACC_PUBLIC, fieldName, fieldDesc, null, null)
+        fv.visitEnd()
+        //method
+        MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, GetLifeMethod, "()" + fieldDesc, null, null)
         mv.visitCode()
         mv.visitVarInsn(Opcodes.ALOAD, 0)
-        mv.visitFieldInsn(Opcodes.GETFIELD, "com/uddream/plugin/LifeCycleDelegate", "\$lifeCycleAresDelegate", "Lcom/uddream/plugin/LifeCycleDelegate;")
+        mv.visitFieldInsn(Opcodes.GETFIELD, LifeClass, fieldName, fieldDesc)
         Label label = new Label()
         mv.visitJumpInsn(Opcodes.IFNONNULL, label)
         mv.visitVarInsn(Opcodes.ALOAD, 0)
         mv.visitVarInsn(Opcodes.ALOAD, 0)
-        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/uddream/plugin/LifeCycleDelegate", "create", "(Ljava/lang/Object;)Lcom/uddream/plugin/LifeCycleDelegate;", false)
-        mv.visitFieldInsn(Opcodes.PUTFIELD, "com/uddream/plugin/LifeCycleDelegate", "\$lifeCycleAresDelegate", "Lcom/uddream/plugin/LifeCycleDelegate;")
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, LifeClass, "create", "(Ljava/lang/Object;)" + fieldDesc, false)
+        mv.visitFieldInsn(Opcodes.PUTFIELD, LifeClass, fieldName, fieldDesc)
         mv.visitLabel(label)
         mv.visitVarInsn(Opcodes.ALOAD, 0)
-        mv.visitFieldInsn(Opcodes.GETFIELD, "com/uddream/plugin/LifeCycleDelegate", "\$lifeCycleAresDelegate", "Lcom/uddream/plugin/LifeCycleDelegate;")
+        mv.visitFieldInsn(Opcodes.GETFIELD, LifeClass, fieldName, fieldDesc)
         mv.visitInsn(Opcodes.ARETURN)
         mv.visitMaxs(0, 0)
         mv.visitEnd()
     }
 
     private int pCount;
+    private String name;
     private Agent agent;
 
-    MethodLifeCycleVisitor(MethodVisitor mv, Agent agent) {
-        super(Opcodes.ASM5, mv, agent.access, agent.name, agent.desc)
+    MethodLifeCycleVisitor(MethodVisitor mv, String name, Agent agent) {
+        super(Opcodes.ASM5, mv)
         this.agent = agent
+        this.name = name
         for (def item : agent.desc.substring(1, agent.desc.indexOf(")")).split(";")) {
             if (!item.equals("")) this.pCount++
         }
@@ -87,16 +127,9 @@ public class MethodLifeCycleVisitor extends GeneratorAdapter {
     @Override
     void visitCode() {
         super.visitCode()
-        //for (int i = 0; i < pCount; i++) loadArg(i)
-        //visitMethodInsn(Opcodes.INVOKESTATIC, LifeClass, agent.name, agent.desc, false)
-    }
-
-    @Override
-    public void visitInsn(int opcode) {
-        if (opcode == Opcodes.RETURN) {
-            //for (int i = 0; i < pCount; i++) loadArg(i)
-            //visitMethodInsn(Opcodes.INVOKESTATIC, LifeClass, agent.name, agent.desc, false)
-        }
-        super.visitInsn(opcode);
+        visitVarInsn(Opcodes.ALOAD, 0)
+        visitMethodInsn(Opcodes.INVOKEVIRTUAL, name, GetLifeMethod, "()L" + LifeClass + ";", false)
+        for (int i = 1; i <= pCount; i++) visitVarInsn(Opcodes.ALOAD, i)
+        visitMethodInsn(Opcodes.INVOKEVIRTUAL, LifeClass, agent.name, agent.desc, false)
     }
 }