0%

Jetpack是什么

2017年I/O大会推出Android Architecture Component,2018年I/O大会推出Jetpack,Support包并入Jetpack中。

来自官方的解释:Jetpack是一个由多个库组成的套件,可帮助开发者遵循最佳做法,减少样板代码并编写可在各种Android版本和设备中一致运行的代码,让开发者精力集中编写重要的代码。

Read more »

前言

Retrofit是square开源的,用于封装网络请求方法和参数的第三方库,开发者使用注解进行网络请求配置,然后转由OkHttp请求网络。

基础用法

  1. 定义接口

    interface Animal {
        @GET("/")
        Call<ResponseBody> get();
    }
  2. 创建Retrofit对象:

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://mtancode.com")
            .build();
  3. 调用接口方法:

    Animal animal = retrofit.create(Animal.class);
        animal.get().enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call,
                                   Response<ResponseBody> response) {
                try {
                    Log.i("test", response.body().string());
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
    
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i("test", "onFailure");
            }
        });

    请求结果在onResponse回调中获取到,该回调运行在UI线程中。

Read more »

一、背景

在之前开发微信小程序时,发现数据绑定用起来比较顺手,代码也变得更简洁,因此抽空研究了Android中DataBinding数据绑定技术的使用和内部原理,该库算比较轻量级,也不需要依赖到很多其它组件,就决定在项目业务中尝试引入使用。

二、项目结构

项目结构分为宿主和插件两部分,所有插件的代码和资源都是独立的,而宿主是共用的,插件可以调用宿主的代码,反过来不行。在最终编译出来的apk中,宿主会打包到dex中,而每一个插件都打包成一个apk形式的包,然后通过DexClassLoader加载进来。

Read more »

前言

Java动态代理可以实现动态生成代理类,而不需要手动写代理类,在使用上比较方便,而代理模式可以用于实现统计,拦截逻辑等统一管理控制的目的,比如在Retrofit中就用到了动态代理。

使用方法

  1. 先定义一个接口:

    interface Animal {
        void eat();
    }
  2. 然后动态生成代理类对象:

    Animal proxy = (Animal) Proxy.newProxyInstance(Animal.class.getClassLoader(), new Class[]{Animal.class},
                (proxy1, method, args1) -> {
                    System.out.println("invoke, " + method.getName());
                    // 调用真实对象的方法
                    return null;
                });
  3. 最后调用方法:

    proxy.eat();

    调用该方法时,就会跑到InvocationHandler的invoke方法中,然后在该方法中去调用真实对象的方法,或者做一些统计逻辑,拦截逻辑等等。

Read more »

在ES7中async和await被正式发布,它们是基于Promise的语法糖,可以用于优化链式代码的写法,让代码更具有可读性,编写逻辑更加清晰。

async

async只需要记住两点就可以:

  1. async函数最终都将返回一个Promise对象,返回值通过resolve的参数传递。

    比如这段代码:

    async function test() {
        return "hello js"
    }

    实际上等价于:

    async function test() {
        return Promise.resolve("hello js");
    }

    因此在调用test函数时,可以在then中获取到结果:

    test().then(value => {
      console.log(value);
    })

    所以所有的async函数都不会阻塞当前后面代码的执行,结果需要在then中获取。

  2. await所在的函数必须加上async。

    这个是语法规定的,没什么好说。

Read more »

一、自定义Gradle插件

步骤如下:

  1. 创建空目录,命名HelloPlugin。

  2. 进入HelloPlugin目录下,新建build.gradle,写如下脚本代码:

    apply plugin: 'groovy'
    apply plugin: 'maven'
    
    dependencies {
        implementation gradleApi()
        implementation localGroovy()
    }
    
    repositories {
        google()
        jcenter()
    }
    
    //将插件打包上传到本地maven仓库
    uploadArchives {
        repositories {
            mavenDeployer {
                pom.groupId = 'com.mtan'
                pom.artifactId = 'HelloPlugin'
                pom.version = '1.0.0'
                repository(url: uri('../repos'))
            }
        }
    }
  3. 新增目录src/main/groovy/com/mtan/plugin,新建HelloPlugin.groovy类,代码:

    package com.mtan.plugin;
    
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    
    public class HelloPlugin implements Plugin<Project> {
    
        public void apply(Project project) {
            println 'HelloPlugin apply'
        }
    }
  4. 新建目录src/main/resources/META-INF/gradle-plugins,新增com.mtan.plugin.properties文件,代码:

    implementation-class=com.mtan.plugin.HelloPlugin
  5. 项目导入idea中,执行uploadArchives任务,即可完成插件上传。

Read more »

Android中实现代码热修复有好几种方法,本文将采用Tinker的修复原理,实现代码,资源,so等热修复。

一、代码修复

1. 原理

原理是比较简单的,本质就是App在运行时,会有个dex数组,当要用到的class不存在时,就顺序从dex数组中寻找,只要找到就停止,因此可以把修复好的dex插入到这个dex数组最前面,那么找的时候就会找到修复好dex中的class,而不再是旧的有问题的class。

Read more »

一、前言

DataBinding库其实出来挺久了,最近工作涉及到跨平台开发,接触到前端的响应式编程,比如微信小程序开发,Vue框架,使用起来还是比较方便的,开发效率也比较高,因此深入分析了Android中的DataBinding库的使用和原理。

二、使用

1. 简单入门

先从最简单的入手,为了让项目支持使用DataBinding,需要在build.gradle中打开开关:

Read more »

Promise用于解决代码嵌套问题,在js中被大量使用,对于如何解决代码嵌套,可以参考文章使用Promise解决代码嵌套问题

要做到熟悉掌握Promise,还需要弄清一些常见的问题,接下来逐一分析。

问题:什么时候会执行catch分支?

先从最简单的开始,只有一个Promise函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
p().then(value => {
console.log('111');
}, reason => {
console.log(reason);
}).catch(e => {
console.log('crash:' + e);
});

function p() {
return new Promise((resolve, reject) => {
throw 'hahaha'
});
}
Read more »

问题

现在有多个请求,第一个请求结束后,失败就结束,成功就继续执行第二个请求,第二个请求结束后,失败就结束,成功就继续执行第三个请求,……,这样一直下去,可能会有三个请求,或者五个请求,或者更多。

原有的解决方法

按照以往的思路,会写出如下的嵌套代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
a(function(res) {
if (res) {
console.log('a执行成功');
b(function(res) {
if (res) {
console.log('b执行成功');
c(function(res) {
if (res) {
console.log('c执行成功');
} else {
console.log('c执行失败,结束');
}
});
} else {
console.log('b执行失败,结束');
}
});
} else {
console.log('a执行失败,结束');
}
});

function a(callback) {
callback(true);
}

function b(callback) {
callback(true);
}

function c(callback) {
callback(true);
}
Read more »