设计模式(九)模版方法模式
本文首发于微信公众号「后厂技术官」
相关文章设计模式系列
1.模版方法模式简介模版方法模式介绍在软件开发中,有时会遇到类似的情况,某个方法的实现需要多个步骤,其中有些步骤是固定的,而有些步骤并不固定,存在可变性。为了提高代码的复用性和系统的灵活性,可以使用模板方法模式来应对这类情况。
模版方法模式定义定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。
模版方法模式结构图
AbstractClass:抽象类,定义了一套算法。
ConcreteClass:具体实现类。
2.模版方法模式的简单实现延续着上一篇设计模式(八)外观模式的写法,我们仍旧来举一个武侠的例子,原谅博主是一个武侠迷。
创建抽象类,定义算法框架一个武侠要战斗的时候,也有一套固定的通用模式,那就是运行内功、开通经脉、准备武器和使用招式,我们把这些用代码表示就是:
public abstract class AbstractSwordsman { //该方法为final,防止算法框架被覆写 public final void fighting ...
Android事件总线(一)EventBus3.0用法全解析
本文首发于微信公众号「后厂技术官」
前言EventBus是一款针对Android优化的发布/订阅事件总线。简化了应用程序内各组件间、组件与后台线程间的通信。优点是开销小,代码更优雅,以及将发送者和接收者解耦。如果Activity和Activity进行交互还好说,如果Fragment和Fragment进行交互着实令人头疼,我们会使用广播来处理,但是使用广播稍显麻烦并且效率也不高,如果传递的数据是实体类需要序列化,那么很显然成本会有点高。今天我们就来学习下EventBus3.0的使用方法。
1.EventBus概述EventBus的三要素EventBus有三个主要的元素需要我们先了解一下:
Event:事件,可以是任意类型的对象。
Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模 ...
Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析
前言我们要实现一个线程安全的队列有两种实现方式一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,本节我们就来研究下ConcurrentLinkedQueue是如何保证线程安全的同时又能高效的操作的。
1.ConcurrentLinkedQueue的结构ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。基于CAS的“wait-free”(常规无等待)来实现,CAS并不是一个算法,它是一个CPU直接支持的硬件指令,这也就在一定程度上决定了它的平台相关性。
当前常用的多线程同步机制可以分为下面三种类型:
volatile 变量:轻量级多线程同步机制,不会引起上下文切换和线程调度。仅提供内存可见性保证,不提供原子性。
CAS 原子指令:轻量级多线程同步机制,不会引起上下文切换和线程调度。它 ...
Android网络编程(七)源码解析OkHttp前篇[请求网络]
本文首发于微信公众号「后厂技术官」
相关文章Android网络编程系列
前言学会了OkHttp3的用法后,我们当然有必要来了解下OkHttp3的源码,当然现在网上的文章很多,我仍旧希望我这一系列文章篇是最简洁易懂的。
1.从请求处理开始分析首先OKHttp3如何使用这里就不在赘述了,不明白的同学可以查看Android网络编程(五)OkHttp2.x用法全解析、Android网络编程(六)OkHttp3用法全解析这两篇文章。当我们要请求网络的时候我们需要用OkHttpClient.newCall(request)进行execute或者enqueue操作,当我们调用newCall时:
@Override public Call newCall(Request request) { return new RealCall(this, request);}
实际返回的是一个RealCall类,我们调用enqueue异步请求网络实际上是调用了RealCall的enqueue方法:
void enqueue(Callback responseCallback, boo ...
Java并发编程(六)阻塞队列
前言在 Android多线程(一)线程池这篇文章时,当我们要创建ThreadPoolExecutor的时候需要传进来一个类型为BlockingQueue的参数,它就是阻塞队列,在这一篇文章里我们会介绍阻塞队列的定义、种类、实现原理以及应用。
1.什么是阻塞队列阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
BlockingQueue有两个常见阻塞场景
当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放入队列。
当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。
那么支持以上两种阻塞场景的队列我们称之为阻塞队列。
BlockingQueue的核心方法放入数据:
offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.(本方法不阻塞当前执行方法的线程) ...
设计模式(八)外观模式
本文首发于微信公众号「后厂技术官」
相关文章设计模式系列
1.外观模式简介外观模式介绍当我们开发Android的时候,无论是做SDK还是封装API,我们大多都会用到外观模式,它通过一个外观类使得整个系统的结构只有一个统一的高层接口,这样能降低用户的使用成本。
外观模式定义为系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得子系统更加容易使用。
外观模式结构图
Facade:外观类,知道哪些子系统类负责处理请求,将客户端的请求代理给适当的子系统对象。
Subsystem:子系统类,实现子系统的功能,处理外观类指派的任务,注意子系统类不含有外观类的引用。
2.外观模式的简单实现在上一篇设计模式之装饰模式我们举了武侠的例子,这一篇我们还举武侠的例子,首先我们把武侠张无忌当作一个系统,他作为一个武侠,他本身分为三个系统分别是招式、内功和经脉。
子系统类(Subsystem)我们知道张无忌的三个系统分别是招式、内功和经脉。那我们来创建它们:
/** * 子系统招式 */public class ZhaoShi { public void TaiJi ...
Java并发编程(五)ConcurrentHashMap的实现原理和源码分析
前言在Java1.5中,并发编程大师Doug Lea给我们带来了concurrent包,而该包中提供的ConcurrentHashMap是线程安全并且高效的HashMap,本节我们就来研究下ConcurrentHashMap是如何保证线程安全的同时又能高效的操作。
1.为何用ConcurrentHashMap在并发编程中使用HashMap可能会导致死循环,而使用线程安全的HashTable效率又低下。
线程不安全的HashMap在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap,如以下代码会导致死循环:
final HashMap<String, String> map = new HashMap<String, String>(2);Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10000; i++ ...
Android View体系(十一)自定义ViewGroup
本文首发于微信公众号「后厂技术官」
前言此前讲了很多,终于可以讲到这一节了,本文的例子是一个自定义的ViewGroup,左右滑动切换不同的页面,类似一个特别简化的ViewPager,这篇文章会涉及到这个系列的很多文章的内容比如View的measure、layout和draw流程,view的滑动等等,所以对View体系不大了解的同学看这篇文章前可以先从头阅读本系列的其他文章,再来看这篇文章效果会更好些。需要注意的是我们知道要实现一个自定义的ViewGroup是很复杂的,这个看看LineraLayout等源码我们就会知道,这里我们只需要把主要的功能实现就好了。
1.继承ViewGroup要实现自定义的ViewGroup,首先要继承ViewGroup并调用父类构造方法,实现抽象方法等。
import android.content.Context;import android.util.AttributeSet;import android.view.ViewGroup;public class HorizontalView extends ViewGroup{ pub ...
Java并发编程(四)Java内存模型
前言此前我们讲到了线程、同步以及volatile关键字,对于Java的并发编程我们有必要了解下Java的内存模型,因为Java线程之间的通信对于工程师来言是完全透明的,内存可见性问题很容易使工程师们觉得困惑,这篇文章我们来主要的讲下Java内存模型的相关概念。
1.共享内存和消息传递线程之间的通信机制有两种:共享内存和消息传递;在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。同步是指程序用于控制不同线程之间操作发生相对顺序的机制。在共享内存并发模型里,同步是显式进行的。工程师必须显式指定某个方法或某段代码需要在线程之间互斥执行。在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对工程师完全透明。
2.Java内存模型的抽象在java中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个 ...
Android View体系(十)自定义组合控件
本文首发于微信公众号「后厂技术官」
前言上一篇我们讲到了自定义View,接着我们来讲讲常用的自定义组合控件,自定义组合控件就是多个控件组合起来成为一个新的控件,主要用来解决多次重复的使用同一类型的布局。比如我们应用的顶部的标题栏,还有弹出的固定样式的dialog,这些都是常用的,所以把他们所需要的控件组合起来重新定义成一个新的控件。
1.组合控件的xml布局我们现在就自定义一个顶部的标题栏,当然实现标题栏有很多的方法,我们来看看自定义组合控件如何去实现。首先我们先定义我们组合控件的布局(view_customtitle.xml):
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_titlebar_rootlayout" android:layout ...
设计模式(七)装饰模式
本文首发于微信公众号「后厂技术官」
相关文章设计模式系列
1.装饰模式简介装饰模式介绍装饰模式是结构型设计模式之一,不必改变类文件和使用继承的情况下,动态地扩展一个对象的功能,是继承的替代方案之一。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
定义动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式结构图
Component:抽象组件,给对象动态的添加职责。
ConcreteComponent:组件具体实现类。
Decorator:抽象装饰者,继承Component,从外类来拓展Component类的功能,但对于Component来说无需知道Decorator的存在。
ConcreteDecorator:装饰者具体实现类。
2.装饰模式的简单实现装饰模式在现实生活中有很多例子,比如给一个人穿上各种衣服,给一幅画涂色上框等等,这次我要举得例子有些不同,举一个武侠修炼武功的例子:杨过本身就会全真剑法,有两位武学前辈洪七公和欧阳锋分别传授杨过打狗棒法和蛤蟆功,这样杨过除了会全真剑法还会打狗棒法和蛤蟆功。
抽象组件(Component)作 ...
Android网络编程(六)OkHttp3用法全解析
本文首发于微信公众号「后厂技术官」
相关文章Android网络编程系列
前言上一篇介绍了OkHttp2.x的用法,这一篇文章我们来对照OkHttp2.x版本来看看,OkHttp3使用起来有那些变化。当然,看这篇文章前建议看一下前一篇文章Android网络编程(五)OkHttp2.x用法全解析。
1.使用前准备Android Studio 配置gradle:
compile 'com.squareup.okhttp3:okhttp:3.2.0'compile 'com.squareup.okio:okio:1.7.0'
添加网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
2.异步GET请求惯例,请求百度:
private void getAsynHttp() { mOkHttpClient=new OkHttpClient(); Request.Builder requestBuilder = ...
Android网络编程(五)OkHttp2.x用法全解析
本文首发于微信公众号「后厂技术官」
相关文章Android网络编程系列
前言讲完了Volley,我们接下来看看目前比较火的网络框架OkHttp, 它处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP,此外OkHttp还处理了代理服务器问题和SSL握手失败问题。
1.使用前准备eclipse引入jar包地址:okhttp-2.7.5.jarokio-1.7.0.jar
Android Studio 配置gradle:
compile 'com.squareup.okhttp:okhttp:2.7.5'compile 'com.squareup.okio:okio:1.7.0'
2.异步GET请求 最简单的get请求,老规矩请求百度:
private void getAsynHttp() { //创建okHttpClient对象 OkHttpClient mOkHttpClient = new OkHttpClien ...
Android网络编程(四)从源码解析Volley
本文首发于微信公众号「后厂技术官」
相关文章Android网络编程系列
1.Volley结构图
从上图可以看到Volley分为三个线程,分别是主线程、缓存调度线程、和网络调度线程,首先请求会加入缓存队列,如果发现可以找到相应的缓存结果就直接读取缓存并解析,然后回调给主线程;如果在缓存中没有找到结果,则将这条请求加入到网络队列中,然后发送HTTP请求,解析响应并写入缓存,并回调给主线程。
2.从RequestQueue入手我们都知道使用Volley之前首先要创建RequestQueue:
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
这也是volley运作的入口,看看newRequestQueue:
public static RequestQueue newRequestQueue(Context context) { return newRequestQueue(context, (HttpStack)null); }public stati ...
Android View体系(九)自定义View
本文首发于微信公众号「后厂技术官」
前言学习了以上的文章后,接下来我们来讲讲自定义View,自定义View一直被认为是高手掌握的技能,因为情况太多,想实现的效果又变化多端,但它也要遵循一定的规则,我们要讲的就是这个规则,至于那些变化多端的酷炫的效果就由各位来慢慢发挥了。但是需要注意的是凡事都要有个度,自定义View毕竟不是规范的控件,如果不设计好不考虑性能反而会适得其反,另外适配起来可能也会产生问题,笔者的建议是如果能用系统控件的还是尽量用系统控件。
1.自定义View简介自定义View按照笔者的划分,分为两大类,一种是自定义View,一种是自定义ViewGroup;其中自定义View又分为继承View和继承系统控件两种。这篇文章首先先了解下两大类的其中一种:自定义View。
2.继承系统控件的自定义View这种自定义View在系统控件的基础上进行拓展,一般是添加新的功能或者修改显示的效果,一般情况下我们在onDraw()方法中进行处理。这里举一个简单的例子:
public class InvalidTextView extends TextView { pr ...
Android网络编程(三)Volley用法全解析
本文首发于微信公众号「后厂技术官」
相关文章Android网络编程系列
前言Volley想必很多人都用过,为了建立网络编程的知识体系,Volley是必须要讲的知识点,所以我这里有必要再次介绍一下Volley的使用。
1.Volley简介在2013年Google I/O大会上推出了一个新的网络通信框架Volley。Volley既可以访问网络取得数据,也可以加载图片,并且在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。在使用Volley前请下载Volley库并放在libs目录下并add到工程中。 下载Volley请点击这
2.Volley网络请求队列Volley请求网络都是基于请求队列的,开发者只要把请求放在请求队列中就可以了,请求队列会依次进行请求,一般情况下,一个应用程序如果网络请求没有特别频繁则完全可以只有一个请求队列(对应Application),如果非常多或其他情况,则可以是一个Activity对应一个网络请求队列,这就要看具体情况了,首先创建队列: ...