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功能的:

还有运行模拟器一开始时,是会有如下提示:

emulator: ERROR: Couldn't find crash service executableC:\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

其实这一个设置就是在更新你项目的.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:        }    }}

编译运行,测试界面为:

添加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的前提下修改代码了。

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

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

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

代码改变 是否支持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/

更多相关文章

  1. Android开发之WebView的使用(1)
  2. Android(安卓)应用保存状态
  3. android热修复--阿里热修复使用和源码分析
  4. Android(安卓)View如何获取焦点
  5. Android(安卓)中ListView setOnItemClickListener点击无效原因分
  6. android 傻瓜式 MultiDex 插件,从此再也不用担心方法数问题!
  7. Android知识梳理之Service整理
  8. 一步一步学习androidNDK编程(hello world)
  9. Android的Context简介

随机推荐

  1. 实战!半小时写一个脑力小游戏 [每日前端夜
  2. 干货!python与MySQL数据库的交互实战
  3. 用python数据分析了北京积分落户名单,发现
  4. Python22个构造函数法-助力数据挖掘与分
  5. 怎样开发可重用组件并发布到NPM [每日前
  6. Node.js多线程完全指南[每日前端夜话0x43
  7. 7 个Web开发工程师面试题和回答策略 [每
  8. 正则表达式在 ES2018 中的新写法 [每日前
  9. 如何用自己喜欢的 CSS 风格重置网站的样
  10. 如何用原生 DOM API 生成表格 [每日前端