Browse Source

add lifecycle agent

weiguo 7 years ago
parent
commit
72d7e4b69d

+ 83 - 0
app/src/main/java/com/uddream/plugin/LifeCycleDelegate.java

@@ -0,0 +1,83 @@
+package com.uddream.plugin;
+
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Created by Glen on 2016/9/8.
+ */
+public abstract class LifeCycleDelegate<T> {
+    protected final T target;
+
+    public LifeCycleDelegate(T target) {
+        this.target = target;
+    }
+
+    public abstract void onCreate(Bundle savedInstanceState);
+
+    public abstract void onResume();
+
+    public abstract void onPause();
+
+    public abstract void onDestroy();
+
+    public abstract void setUserVisibleHint(boolean isVisibleToUser);
+
+    public abstract void onHiddenChanged(boolean hidden);
+
+    public abstract void onSaveInstanceState(Bundle outState);
+
+    public abstract void onRestoreInstanceState(Bundle savedInstanceState);
+
+    @SuppressWarnings("unused")
+    public static LifeCycleDelegate create(Object object) {
+        return new Empty(object);
+    }
+
+    public static class Empty extends LifeCycleDelegate<Object> {
+
+        public Empty(Object target) {
+            super(target);
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            Log.e("Delegate", "onCreate");
+        }
+
+        @Override
+        public void onResume() {
+            Log.e("Delegate", "onResume");
+        }
+
+        @Override
+        public void onPause() {
+            Log.e("Delegate", "onPause");
+        }
+
+        @Override
+        public void onDestroy() {
+            Log.e("Delegate", "onDestroy");
+        }
+
+        @Override
+        public void setUserVisibleHint(boolean isVisibleToUser) {
+
+        }
+
+        @Override
+        public void onHiddenChanged(boolean hidden) {
+
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle savedInstanceState) {
+
+        }
+    }
+}

+ 15 - 1
app/src/main/java/com/uddream/plugin/MainActivity.java

@@ -4,7 +4,6 @@ import android.os.Bundle;
 import android.support.design.widget.FloatingActionButton;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
-import android.util.Log;
 import android.view.View;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
@@ -14,6 +13,8 @@ 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) {
@@ -24,6 +25,7 @@ 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);
@@ -36,6 +38,11 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
     }
 
     @Override
+    protected void onPause() {
+        super.onPause();
+    }
+
+    @Override
     public void onClick(View v) {
         System.out.print("onClick listener");
     }
@@ -44,4 +51,11 @@ 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;
+//    }
 }

+ 28 - 0
buildSrc/src/main/groovy/com/gradle/ares/Agent.groovy

@@ -0,0 +1,28 @@
+package com.gradle.ares;
+
+/**
+ * Created by Glen on 2017/2/8.
+ */
+
+public class Agent {
+    int access;
+    String name;
+    String desc;
+
+    Agent(String name, String desc) {
+        this.name = name
+        this.desc = desc
+    }
+
+    public int getAccess() {
+        return access;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

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

@@ -4,6 +4,7 @@ import org.gradle.api.Project
 import org.gradle.api.logging.Logger
 import org.gradle.api.logging.Logging
 import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
 import org.objectweb.asm.MethodVisitor
 import org.objectweb.asm.Opcodes
 
@@ -20,6 +21,8 @@ public class ClassAdapter extends ClassVisitor {
     private String superName;
     private String[] interfaces;
 
+    private Set<Agent> addAgents;
+
     public ClassAdapter(ClassVisitor cv, Project project) {
         super(Opcodes.ASM5, cv)
         this.project = project
@@ -42,11 +45,34 @@ public class ClassAdapter extends ClassVisitor {
         if (agent != null) {
             modify = true
             debug("method:" + access + "_" + name + "_" + desc)
-            return new MethodAgentVisitor(mv, agent)
+            mv = new MethodAgentVisitor(mv, agent)
+        }
+
+        agent = MethodLifeCycleVisitor.getAgent(superName, access, name, desc)
+        if (agent != null) {
+            debug("lifecycle:" + access + "_" + name + "_" + desc)
+            if (addAgents == null) addAgents = new HashSet<>();
+            addAgents.add(agent)
+
+            modify = true
+            mv = new MethodLifeCycleVisitor(mv, agent)
         }
         return mv
     }
 
+    @Override
+    FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+        return super.visitField(access, name, desc, signature, value)
+    }
+
+    @Override
+    void visitEnd() {
+        if (addAgents != null) {
+            MethodLifeCycleVisitor.addMethods(addAgents, this.cv)
+        }
+        super.visitEnd()
+    }
+
     boolean getModify() {
         return modify
     }

+ 0 - 11
buildSrc/src/main/groovy/com/gradle/ares/MethodAgentVisitor.groovy

@@ -52,15 +52,4 @@ public class MethodAgentVisitor extends GeneratorAdapter {
         }
         super.visitInsn(opcode);
     }
-
-    public static class Agent {
-        int access;
-        String name;
-        String desc;
-
-        Agent(String name, String desc) {
-            this.name = name
-            this.desc = desc
-        }
-    }
 }

+ 102 - 0
buildSrc/src/main/groovy/com/gradle/ares/MethodLifeCycleVisitor.groovy

@@ -0,0 +1,102 @@
+package com.gradle.ares
+
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+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 final static String LifeClass = "com/uddream/plugin/LifeCycleDelegate";
+
+    public final static String[] SuperClass = [
+            "android/app/Activity",
+            "android/support/v4/app/FragmentActivity",
+            "android/support/v7/app/AppCompatActivity",
+            "android/support/v4/app/Fragment",
+            "android/support/v4/app/ListFragment",
+            "android/support/v4/app/DialogFragment",
+            "android/app/Fragment",
+            "android/app/ListFragment",
+            "android/app/DialogFragment"
+    ] 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"),
+            new Agent("onDestroy", "()V"),
+            new Agent("onSaveInstanceState", "(Landroid/os/Bundle;)V"),
+            new Agent("onRestoreInstanceState", "(Landroid/os/Bundle;)V"),
+            new Agent("setUserVisibleHint", "(Z)V"),
+            new Agent("onHiddenChanged", "(Z)V")
+    ] as Agent[]
+
+    public final static Agent getAgent(String superName, int access, String name, String desc) {
+        for (String s : SuperClass) {
+            if (s.equals(superName)) {
+                for (Agent item : Modify) {
+                    if (item.name.equals(name) && item.desc.equals(desc)) {
+                        item.access = access
+                        return item
+                    }
+                }
+                break
+            }
+        }
+        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)
+        mv.visitCode()
+        mv.visitVarInsn(Opcodes.ALOAD, 0)
+        mv.visitFieldInsn(Opcodes.GETFIELD, "com/uddream/plugin/LifeCycleDelegate", "\$lifeCycleAresDelegate", "Lcom/uddream/plugin/LifeCycleDelegate;")
+        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.visitLabel(label)
+        mv.visitVarInsn(Opcodes.ALOAD, 0)
+        mv.visitFieldInsn(Opcodes.GETFIELD, "com/uddream/plugin/LifeCycleDelegate", "\$lifeCycleAresDelegate", "Lcom/uddream/plugin/LifeCycleDelegate;")
+        mv.visitInsn(Opcodes.ARETURN)
+        mv.visitMaxs(0, 0)
+        mv.visitEnd()
+    }
+
+    private int pCount;
+    private Agent agent;
+
+    MethodLifeCycleVisitor(MethodVisitor mv, Agent agent) {
+        super(Opcodes.ASM5, mv, agent.access, agent.name, agent.desc)
+        this.agent = agent
+        for (def item : agent.desc.substring(1, agent.desc.indexOf(")")).split(";")) {
+            if (!item.equals("")) this.pCount++
+        }
+    }
+
+    @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);
+    }
+}