Android Studio 2.0--如何使用新模拟器以及Instant Run

2.0新的模拟器简易上手流程


安装
让我们从安装开始,这样你就可以跟着一步一步的来。

  • 第一个要安装的就是Android Studio 2.0 Preview 3b,在 Canary Channel上有提供。要把更新channel转换到Canary,只需点击Help -> Check for Update…并把最上面的下拉菜单改为 Canary Channel,完了之后,再次检查更新然后Android Studio 2.0 就会安装在你的机器上了。

  • 安卓模拟器2.0是和Android SDK Tools v25(或者更新)的版本一起 的。所以接下来你要安装的就是Android SDK Tools v25 rc1 ,它可以通过SDK Manager来完成。以及安装最新的 Intel x86 Emulator Accelerator (HAXM installer),并且下载的只是一个安装器,所以需要在SDK里手动安装,路径如下:extras/intel/Hardware_Accelerated_Execution_Manager

  • 有时候安装时会报错,需要设置控制面板->程序与功能->启用或关闭Windows功能->去掉 Hyper-V选项,就可以成功安装了。

  • 最后是下载Android 5.0 - Google APIs Intel x86 Atom System Image rev 10,把它作为模拟器的rom镜像。

这样就准备完毕,可以使用了。
使用过程中发现太吃内存了这个模拟器,运存8G以上才可能不太卡。

效果如下,并且是可以使用Instant Run功能的:
Android Studio 2.0--如何使用新模拟器以及Instant Run_第1张图片

还有运行模拟器一开始时,是会有如下提示:
Android Studio 2.0--如何使用新模拟器以及Instant Run_第2张图片

emulator: ERROR: Couldn't find crash service executable
C:\Users\user\AppData\Local\Android\sdk\tools\emulator64-crash-service.exe
...

虽然不懂为什么报这个,但是我现在是直接无视它运行模拟器的呃。。。

Android Studio 2.0 Instant Run 的预设置


Update Project 使得能够使用Instant Run功能

首先你需要去设置中启用Instant Run:

  • 在Mac的运行环境中,点击 Android Studio → Preferences
  • 在Windows的运行环境中,点击 File → Settings

新项目需要在 Build, Execution, Deployment → Instant Run 点击 Update Project,然后点击 OK
Android Studio 2.0--如何使用新模拟器以及Instant Run_第3张图片

其实这一个设置就是在更新你项目的.gradle文件,并且使用最新版本的Android gradle插件,使得Instant Run 功能生效。

更新后的.gradle文件如下:

buildscript {
   repositories {
       jcenter()
   }

   dependencies {
       classpath 'com.android.tools.build:gradle:2.0.0-alpha1'
   }
}

好,现在可以来试试运用一下Instant Run 。
点击”Run“ 使你的程序在模拟器或者设备上跑起来~

我测试使用的设备是:Meizu M1 Note(Android 5.1 ,API 22)
测试代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{


    private Button run;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        run = (Button) findViewById(R.id.button);
        run.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:

        }
    }
}

编译运行,测试界面为:

Android Studio 2.0--如何使用新模拟器以及Instant Run_第4张图片

添加Toast:

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                Toast.makeText(MainActivity.this, "Instant Run!!", Toast.LENGTH_SHORT).show();
        }

现在,只要点击工具栏上的Instant Run按键就可以在不重新安装apk的前提下修改代码了。
Android Studio 2.0--如何使用新模拟器以及Instant Run_第5张图片

你会发现,系统瞬间就响应了你的点击行为,并且发出一条提示:
Applied changes,restarted acticity

Android Studio 2.0--如何使用新模拟器以及Instant Run_第6张图片

现在,点击按键,你会发现你已经运行的是修改后的代码,是不是感觉特别棒!

Android Studio 2.0--如何使用新模拟器以及Instant Run_第7张图片

可惜现在这个功能估计还在研发阶段,不是所有的代码修改情况都支持,支持该功能的情况不多,如下:

代码改变 是否支持Intant Run
改变实例方法实现
改变静态方法实现
添加或删除一个类
添加、删除或修改一个字符串资源 支持但是需要活动重启

以下为不支持Instant Run 的情况:

  • 添加/删除/修改实例字段
  • 添加/删除/修改注释
  • 添加/删除/改变静态字段
  • 添加/删除一个静态方法签名
  • 改变一个静态方法签名
  • 添加/删除一个实例方法
  • 改变一个实例方法签名
  • 改变当前类继承自父类
  • 变化的列表实现的接口
  • 改变类的静态初始化器

在我测试的情况来看,这个功能还不够稳定,代码修改后,经常不会触发Instant Run 的效果,而是直接重新安装。

但我觉得我大谷歌应该很快就完善好这一如此“便民”的功能。

转载自大神对Instant Run的分析


Instant Run

google官方关于Instant Run特性的介绍在这里:https://sites.google.com/a/android.com/tools/tech-docs/instant-run,按其所述,运行FloatingActionButtonBasic样例,实验Instant Run,豪爽豪爽。

但是,修改方法竟然不用重启Activity,这是怎么做到的?

阅读一帆关于几个热补丁思路的介绍,你会发现andfix和dexposed采用jni hook方法,不用重启就能修复,而Nuwa的ClassLoader思路因为类被虚拟机加载后,不会重新加载,所以需要重启。Instant Run是怎么实现不重启加载的呢,难道也是jni hook?

实现原理

和nuwa类似,一个插件一个库,Instant Run用的是gradle plugin 2.0.0-alpha1和instant-run.jar。

gradle plugin 2.0.0-alpha1

gradle plugin 2.0.0-alpha1主要有两个作用:

  • 第一次运行,应用transform API修改字节码。
    输出目录为:
    Application/build/intermediates/transforms/instantRun/debug/folders/1。

    • 给所有的类添加change字段
      change为IncrementalChange类型,IncrementalChange是个接口,该接口后面会讲。

    • 修改类的全部方法
      新的逻辑是:如果change不为空,去调用 changeaccess dispatch方法,参数为方法签名字符串和方法参数数组,否则调用原逻辑。

  • 后续运行,dx补丁类,生成补丁dex。
    输出目录为:
    Application/build/intermediates/transforms/instantRun/debug/folders/4000。

    • 被修改类对应的补丁类
      补丁类,并不是你修改后的类,而是由gradle plugin自动生成,实现了IncrementalChange接口的类。
      该类类名在原名后面添加override,复制修改后类的大部分方法,实现IncrementalChange 接口的accessdispatch方法,该方法会根据传递过来的方法签名,调用本类的同名方法。
      只要把原类的change字段设置为该类,那就会调用该类的accessdispatch方法,就会使用修改后的方法了。

    • 被修改类的记录类
      AppPatchesLoaderImpl记录了所有被修改的类,也会被打进补丁dex。

instant-run.jar

instant-run.jar的路径为Application/build/intermediates/incremental-runtime-classes/debug/instant-run.jar。

instant-run.jar是gradle plugin帮我们自动打到dex中去的,省去了compile dependency这一步。它的主要作用有两个:

  • 设置原类的$change字段为补丁类

    需要对被修改的类设置change字段,那怎么知道哪些类被修改了?
    AppPatchesLoaderImpl类不但记录了全部被修改的类,还提供load方法支持设置被修改原类change字段,当收到补丁通知时,只需新建一个DexClassLoader,去反射加载补丁dex中的AppPatchesLoaderImpl类,调用load方法即可,load方法中会去加载全部补丁类,并赋值给对应原类的change。

  • 重启加载补丁类

    重启后怎么办?原来的补丁文件需要加载进来。

    IncrementalClassLoader会在Application中去加载该应用cache目录中的补丁dex,把它设置为默认PathClassLoader的parent,由于ClassLoader采用双亲委托模型,会先去parent查找类,所以就可以加载补丁类了。

总结

google的介绍中,也提到了Instant Run的一些局限之处,比如变量、添加删除方法等,当然这一切都会持续优化,gradle plugin 2.0也还仅仅是个alpha版本而已。

Instant Run的实现思路蛮笨的,几乎所有的方法都修改逻辑,但不用重启这一点很赞,用这个思路可以搞一个热修复库了,有官方背景的库。

本文主要是探究Instant Run处理代码变化的思路,对资源变化没有分析,对于一些细节比如server实现、socket传输、application替换、updateMode处理亦未提及。

原文出处:http://jiajixin.cn/2015/11/25/instant-run/

你可能感兴趣的:(Android匍匐)