撸个简单的 JSbridge
这两年 Web 技术栈一直在努力地向移动端和后端延展(这里没有引战的意思),当然这也是技术发展所带来的必然结果。移动互联网早期主要以原生开发为主,但到现在,业务不断发展,版本也需要快速迭代,原生开发效率很明显难以跟上,这时候 Web 开发的优势就显现出来了。 (废话讲的差不多了) HybridHybrid App 中文名叫:混合App,即原生应用和 WebApp 的结合体,它兼顾了 原生应用 的体验和 WebApp 的开发效率(这里定义应该是狭义的)。最常见的 Hybrid 的实现方式是通过 JSBridge 来打通 Native Code 和 JavaScript 之间的隔阂。这篇文章中我们一起来简单实现一个 JSBridge。 背景知识在 Android 上实现 Hybrid 是通过 Webview 来实现的,所以下面再简单过一下 Webview 的一些基本知识。 Webview通常我们会使用 webview.loadUrl(url) 来加载一个页面,这个方法还可以用来执行 JS 代码: 1webview.loadUrl("javascript:console.log ...
Docker 安装
这篇文章真不知道怎么写描述,很尴尬的开头。只是简单的记录一下 Docker 的安装和常用的操作命令。 安装 这里安装的是 Docker-ce,满足我们的学习需求是完全没有问题的 我使用的是 Ubuntu 17.04 系统要求Docker 要求我们的操作系统(Ubuntu)必须是 64-bit,同时必须是下面这些版本: Artful 17.10 (Docker CE 17.11 Edge and higher only) Zesty 17.04 Xenial 16.04 (LTS) Trusty 14.04 (LTS) 虽然可能不是这些版本也能安装成功,但是可能官方文档上的一些操作可能会执行失败,所以最妥当的方法就是使用长期支持版本(LTS) 卸载旧版本Docker 目前版本和之前的版本名称有改变,所以需要卸载以前的版本,如果这是你第一次安装的话,可以跳过。终端执行一下命令: 1$ sudo apt remove docker docker-engine docker.io 你的镜像、容器等不会被一起清除,它们还呆在 /var/lib/docker/ 目录下 安装安装 ...
Activity 生命周期
Activity 的生命周期是每位 Android 开发都必须掌握的基本知识,以致于几乎所有的 Android ,入门书籍在前几章就会开始讲生命周期。这篇文章大体上是官方文档的个人理解,内容上可能会有一些出入。 定义随着用户的操作,应用会在几个状态之间进行一系列的切换,映射到 Activity 上就是一系列的生命周期回调:onCreate()、onStart()、onResume()、onPause()、onStop() 以及 onDestroy()。当 Activity 切换到不同的状态时,系统会调用对应的生命周期回调方法。 下图是官方对 Activity 状态转移的图示: 通过重写这些生命周期方法,以便在适当的时候做出处理,比如保存数据、停止音乐、释放数据库连接等,根据应用的复杂程度,并不是必须重写所有的生命周期回调方法。 生命周期方法这一节会分别对主要生命周期回调进行一些说明。 onCreate()这个方法一般情况下必须重写,系统创建 Activity 实例之后就会调用这个方法,Activity 进入 Created 状态。这个回调方法里面主要完成一些整个 Activity ...
Retrofit 拆轮子之构建流程分析
在使用 OkHttp 的时候,还是要自己构建 Request 的,我们的目的是请求一个 url 并拿到数据,构建流程不利于逻辑清晰,特别是当需要 Post 上传数据的时候。Square 显然是看到了这个问题,便推出了 Retrofit 来解决这个问题。 Retrofit 使用注解的方式来定义一个后端接口,在 运行时 解析,动态构建出请求逻辑并执行。有时候还是会遇上一些坑,所以最快捷的方式就是阅读它的源码,知道了内部逻辑,自然而然就知道了问题出在哪里。 这里基于 Retrofit:2.4.0-SNAPSHOT 分析 构建流程分析Retrofit 简化请求的构建,使得网络请求就像简单的函数调用一样。这次就分析下面的案例: 1234567891011121314interface MyService { @GET("/user") Observable<User> getUser();}Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://exa ...
再见,2017!!!
今天元旦,2018 年的第一天,也琢磨着是不是该写写什么,就这么过去似乎太平淡了。思前想后,留有印象的事情好像就那么几件,似乎每天都是差不多的生活——看文章、写代码。 公历农历真是神奇的东西,今年明年怎么算一时半会竟然还糊涂了,那还是按照公历来算吧。 去年这个时候,差不多也是临近期末,既要准备考试,又要忙于项目。有时候真想什么都甩手不敢,去他妈的考试,干他妈的项目。也就想想,生活还是要继续。 2 月份就已经放寒假了,还是像往常一样,继续待在学校(自从进了高中就是这样)。到现在热记忆犹新的,还是回家居然买反了票,虽然取票的时候觉得哪里不对,取出来硬是盯了半天才发现问题。不过运气还不算太差,人工窗口那买到了回家的票,虽然只能在岳阳暂住一晚。比较神奇的是,半路上高中同学突然联系(怕是一年半没联系过了),约着出去浪了一波,蹭了顿饭,之后还建了个群水到现在hhh。 然后春节还是那么无聊,正月里9号就滚回了学校,元宵节就和俩傻逼在外面兜了个大圈子,还特么和几个陌生妹子建了个微信群,狗血。比较遗憾的是春游没有和大家一起泡温泉,不过和其他人玩狼人杀也很开心。 上半年,上了我的第一款App,虽然 ...
Dagger2 上手指南
在 Java 的开发中,怎么利用各种设计模式和架构设计来解耦、提高拓展性,似乎已经成了一名 Java 开发人员的必修课。在一些大型系统中,还会有各种听起来高大上的名词,如 IOC、OSGI、CGLIB 等。所以这里我们就来讲讲 IOC 的一个实现框架——Dagger2。 IOC/DI 什么是 IOC(inverse of control)? IOC 是一种面向对象编程中的一种设计原则,主要用来降低代码之间的耦合度。主要手段是通过 第三方工具 实现具有依赖关系代码之间的解耦。 IOC 名称的含义? 考虑两种情况: 类 A 需要类 B 的实例,A通过 new 关键字来创建实例,这时创建和使用都是 A 做主。 类 A 需要类 B 的实例,但是并没有主动使用 new 关键字,这时 A 只能被动接受外部传递给它的实例。 对比两种情况,第二种情况中 A 失去了对 B 的控制权,获取 B 的过程由主动变为被动。 什么是 DI(Dependency Injection)? DI 就是将某个实例通过某种方式传递给需要这个实例的地方。 IOC 与 DI IOC 是一种工程思想 ...
Hexo 搭建静态博客
上次搭的博客写了两篇 Hexo 的配置后就凉了,所以这次刚刚搭好的时候就没想做个记录,怕和上次一样,把写博客的热情全花在了搭建博客上。 系统平台是 Ubuntu 17.04,其他平台的安装过程可能会有一些不同,不过后面的配置还是一样的。这里只有安装配置过程,具体使用,还请移步官方文档。建议先看完再进行操作!!! 安装hexo 是一个基于 node 的静态博客生成工具,所以先安装 node : 1sudo apt install nodejs 这样安装似乎没有像 windows 下那样顺带把 npm 也给安装了,所以还需要安装一下 npm : 1sudo apt install npm 再接着安装 Hexo: 1sudo npm install hexo -g 很多朋友会遇到 Permission denied 的错误,所以我们需要使用 sudo 安装 1234# 在有读写权限的目录下执行,Blog 可以换成你喜欢的名字mkdir Blog && cd Blog# 初始化 Bloghexo init 不出问题,写作环境就安装好了,再测试下: 1234# 生成静 ...
Annotation 基础
注解是一种元数据(metadata),它在虽然能提供关于程序的一些信息,但并不是程序本身的一部分。注解对被其标注的对象没有任何副作用。 关于注解的作用,主要有以下三点: 为编译器提供信息:比如语法检查等 在编译或部署时进行一些处理:比如生成一些报表信息 运行时:主要通过反射来操作 这里假设读者对注解有一定的了解 表现形似@Override 应该最常见的注解之一,比如一些注解可能还会有参数,那么就有点像 Java 的构造函数,不过参数位置没有固定,所以也就需要显示指定参数的名称和值。 分类 元注解(meta-annotation): 用来自定义注解时使用 标注注解: 即 JDK 自带的,有 Override,Deprecated 等 自定义注解: 即我们为满足某种需求而自定义的注解 自定义注解最快学习 Annotation 的方式还是自定义注解,下面我们就来定义一个 Message 注解: 1234567@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.CLASS)publ ...
OkHttp 拆轮子之连接池
OkHttp 内部还维护了一个连接池,用于缓存一定数量的连接,以减少与服务器建立连接时的资源开销。同时,为了保证缓存的连接数在一个合理的水平,连接池有一个最多闲置连接数量和最长连接闲置时长。这里我们还是通过分析一些关键方法来分析它的连接池机制: ConnectionPool#get()这个方法用于从连接池中获取一个可用的连接。 123456789RealConnection get(Address address, StreamAllocation streamAllocation, Route route) { for (RealConnection connection : connections) { if (connection.isEligible(address, route)) { streamAllocation.acquire(connection); return connection; } } return null; ...
ThreadLocal 源码分析
在并发编程的时候,常常会遇到共享变量,通常为了保证数据的 一致性 ,需要对变量加锁,这就导致了执行效率的降低。如果仅仅在线程内部访问,就不需要进行加锁,这时候就体现出了数据的 独立性 (这两个名词是随手造的,知道意思就好了)。 ThreadLocal 类能够帮助我们实现数据独立性,它保证了线程单独持有一个变量,并且对这个变量的操作不会影响其它线程的值。具体的情况可能和我讲的你所理解的有些出入,下面我们通过源代码来深入探究。 提供的API正式开始之前,先看看 ThreadLocal 这个类给我提供了哪些API set(T value) 给当前线程设置一个 ThreadLocal 值 的拷贝 T get() 获取当前线程保存的 ThreadLocal 值 的拷贝 remove() 移除当前线程保存的拷贝 T initialValue() 当当前线程通过 get() 来第一次访问 Threadlocal 的时候被调用,然后会返回一个 T ,默认返回是 null 。 如果调用了 remove(),下一次又调用 get() ,这个方法还会被调用 下面简单使用一下: 12345678 ...