0%

前言

一般情况下,在Java层可以使用动态代理实现方法hook,如下:

interface Animal {
    void eat();
}

Object proxy = Proxy.newProxyInstance(getClassLoader(), new Class[]{Animal.class},
        new InvocationHandler() {
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        return null;
    }
});
// 反射替换为动态代理对象proxy
//
Read more »

问题

最近遇到个问题,项目apk中包含有libc++.so,这个so会影响二次打包,导致打出来的包的所有so都不会被压缩,因此apk会变得大很多。

我们需要知道这个libc++.so来自哪里,由于项目依赖的第三方sdk很多,而且还有各种传递依赖,直接一个一个找并不现实。

这时我们可以找到gradle处理so的task,名称位transformNativeLibsWithMergeJniLibsForDebug,然后把输入参数打印出来,就可以很清楚地看到每一个so的来源路径。

Read more »

var和Object和dynamic区别

var在没初始值时可以变成任意类型,有初始值后就固定为对应的类型。

Object可以是任意类型,编译时会进行静态检查,对应不上会导致编译失败。

dynamic可以是任意类型,编译时不会进行静态检查,如果对应不上,能编译通过,运行时会crash。

??和??=和?.

a = b ?? "hello"; // 如果b不为null,就赋值给a,否则赋值hello给a
a ??="hello"; // 如果a为null,就赋值hellp给a
print(a?.hashCode); // 如果a为null,就不调用,打印null,否则调用hashCode
Read more »

package_info_plus源码分析

package_info_plus用于获取对应平台的包信息(注意只是获取自己的),目前最新版本是1.3.0。

使用时,调用fromPlatform方法,就可以拿到对应平台的自身包信息,fromPlatform方法源码如下:

static Future<PackageInfo> fromPlatform() async {
    if (_fromPlatform != null) {
      return _fromPlatform!;
    }

    final platformData = await _platform.getAll();
    _fromPlatform = PackageInfo(
      appName: platformData.appName,
      packageName: platformData.packageName,
      version: platformData.version,
      buildNumber: platformData.buildNumber,
      buildSignature: platformData.buildSignature,
    );
    return _fromPlatform!;
  }
Read more »

一、问题

测试那边反馈有问题,自测没问题,由于各种原因无法拿测试手机亲自调试,因此只能是测试复现问题,然后给日志,开发根据日志定位问题原因。

前提:代码逻辑复杂,流程复杂,或者是刚接手过来的项目,如何快速地定位到整个流程中哪一步出了问题?

二、分析

方案一:叫测试给指定tag的日志,因为代码逻辑复杂类多,很难一次性给出所有的tag,后面发现日志缺失后再去叫测试补日志很浪费时间。

Read more »

前言

Flutter的组件很多,接下来介绍开发过程中常见的一些组件,先上类图:

常见组件

基本组件

  • Text

    文本组件。

  • Image

    图片组件。

  • RaisedButton、FlatButton、OutlineButton、IconButton

    按钮组件,也可以实现样式自定义。

  • Icon

    图标组件。

  • TextField

    输入框组件。

Read more »

一、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 »