RxJava API使用示例
概述
详细
一、项目概述
本Demo是为了方便大家了解RxJava的API,我将所有的RxJava API(至少是官方文档中提到的)都写在一个android apk中,并在其中附以功能描述,代码示例,marble-diagram(Rx用来描述数据及其处理流程的图), 以及一些使用场景. 所有的资料都是在APK中,使用的时候不会消耗任何流量,而且你可以在任何时候任何地方学习使用.
示例程序的特点如下:
1. API涵盖全面: 包含了核心库及所有扩展实现库200个左右的API.
2. 数据本地化,无需流量: 示例中的所有数据和图片都是本地加载的,所以无需消耗流量.
3. 示例代码都是从源码中直接生成,所以看起来跟代码直接运行的效果是一样的
二、主界面展示
上图为整个Demo的运行示例截图:
左边为Rxjava主要组件及运算符类别入口
右边为单个运算符的marble-diagram, 详细的运算符列表,代码示例以及代码的执行结果。
点击相应的运算符,界面会切换到该运算符的marble-diagram以及示例代码,同时会执行该代码,将执行结果输出到结果区。
三、代码实现
在整个Demo中,主要部分就是RxJava API运算子的呈现,包括marble图,API描述,示例代码,运算结果的展现
及不同运算子切换的交互。
所有的UI组成部分都是以插件的形式插入到Demo的UI体系中,设计图如下:
APIBaseActivity: API详情主Activity,包含了重定向输出结果到结果view以及整合DisplayPluginManager中所有View的展示的功能。
DisplayPluginManager: 管理所有的展示Plugin。
Plugin: 展示Plugin的接口类,主要负责根据不同的操作符ID提供不同的插件View。
MarbleDiagramPlugin: Marble图展示插件。
DescriptionPlugin: API描述展示插件。
SampleCodePlugin: 示例代码展示插件。
下边详细介绍这四部分的核心实现:
Marble图
marble图的地址是我在看官方文档的时候,手动扣取的,所有地址都保存在项目的MarbleDiagramPlugin.java中
最初demo使用的是动态获取marble图地址,由于原图需要消耗流量且图片较大,所以我是将所有图片从网络拉取到本地直接打包到apk中,而且在这个过程中对图片进行了进一步的打包压缩。
读取marble地址配置
# 将原来的注册地址的代码块处理并读取出来
def ProcessRegisterBlock(lines):
if len(lines) == 0:
return None
mb = []
for line in lines:
line = line.strip('\r\n ,);')
line = line.replace('\"','');
if len(line) < 10 or not line.startswith('http'):
continue mb.append(line)
return mb # 查找到Constants对应的Key
def FindKey(line):
start = line.find('Constants.')
end = line.find(',',start)
return line[start: end] # 将名称转化为android的资源描述符名称
def Url2Id(url):
start = url.rfind('/')
if start < 0:
return None
return 'R.drawable.' + url[start + 1:].replace('.','_').lower() codes = {}
# 拼装待生成的目标代码的路径
dest = os.path.join('app','src','main','java','union','uc','com','rxjava_example','plugin')
if not os.path.exists(dest):
os.path.makedirs(dest) key = ""
# 打开marble图地址配置源码文件,并逐行扫描处理
with open(os.path.join(dest, 'MarbleDiagramPlugin.java'), 'r') as input:
block = []
find_add = False
for line in input:
if len(line.strip()) == 0:
continue
if line.find('add(Constants.') >= 0:
find_add = True
if len(block) > 0:
code= ProcessRegisterBlock(block)
codes[key] = code
block = []
key = FindKey(line)
http_start = line.find('\"http')
if http_start >= 0:
http_end = line.find('\"', http_start + 1)
if http_end >= 0:
block.append(line[http_start:http_end])
elif find_add:
block.append(line)
if find_add and len(block) > 0:
code= ProcessRegisterBlock(block)
codes[key] = code
2. 生成Marble图资源配置文件
# 新建marble图资源配置文件
with open(os.path.join(dest,'MarbleDiagram.java'),'w') as output:
# 生成header
header = '''
package union.uc.com.rxjava_example.plugin; import java.util.HashMap;
import java.util.Map;
import union.uc.com.rxjava_example.contants.Constants;
import union.uc.com.rxjava_example.R;
public class MarbleDiagram{
private Map<String, Integer[]> mCodes = new HashMap<>();
public MarbleDiagram(){
'''
footer = '''
}
public Integer[] get(String key){
return mCodes.get(key);
}
private void add(String key, Integer... urls) {
mCodes.put(key, urls);
}
}
'''
output.write(header)
# 生成footer
for key,code in codes.items():
if code == None:
continue
s = ""
if len(code) == 1:
code0 = Url2Id(code[0])
s = '\nadd(%s,%s);' % (key, code0)
elif len(code) == 2:
code0 = Url2Id(code[0])
code1 = Url2Id(code[1])
s = '\nadd(%s,%s,%s);' % (key, code0, code1)
elif len(code) == 3:
code0 = Url2Id(code[0])
code1 = Url2Id(code[1])
code2 = Url2Id(code[2])
s = '\nadd(%s,%s,%s,%s);' % (key, code0, code1, code2)
elif len(code) == 4:
code0 = Url2Id(code[0])
code1 = Url2Id(code[1])
code2 = Url2Id(code[2])
code3 = Url2Id(code[3])
s = '\nadd(%s,%s,%s,%s,%s);' % (key, code0, code1, code2, code3)
output.write(s)
output.write(footer)
#下载图片
dir_drawable = os.path.join('app', 'src', 'main', 'res', 'drawable')
for key,code in codes.items():
if code != None:
for c in code:
os.system('wget %s -P imgs' % (c ))
# 重命名图片
for root, dirs, files in os.walk('imgs'):
for file in files:
src = os.path.join(root,file)
dest = os.path.join(dir_drawable, file.lower().replace('.', '_') + '.png')
os.rename(src, dest)
3. 压缩图片,为减小API尺寸,对marble图进行了简单压缩
dir_drawable = os.path.join('app', 'src', 'main', 'res', 'drawable')
for root, dirs, files in os.walk(dir_drawable):
for file in files:
if not file.endswith('.png'):
continue
src = os.path.join(root,file)
img = Image.open(src)
img = img.resize((400,200),Image.ANTIALIAS)
img.save(src)
del img
API描述
API描述UI插件的实现是在DescriptionPlugin中,该Plugin主要是根据操作符id生成TextView并设置内容文本。
public class DescriptionPlugin implements DisplayPluginManager.Plugin {
@Override
public Tuple.Tuple2<Observable<View>, View> getView(final Context context, String key) {
// 创建描述TextView, 为提高内存性能,避免无效引用,使用WeakReference.
final TextView textView = new TextView(context);
final Reference<TextView> ref = new WeakReference<>(textView);
Observable<View> o = Observable.just(key)
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
// 如果资源列表为空,则加载资源列表
if (mKeyToResource == null) {
load();
}
// 读取id对应的资源文本内容
return mKeyToResource.get(s);
}
}).map(new Func1<Integer, View>() {
@Override
public View call(Integer integer) {
// 更新TextView 文本
textView.setText(integer);
return textView;
}
}); return new Tuple.Tuple2<>(o, (View) textView);
}
API示例代码
示例代码的实现是在SampleCodePlugin中,其实现逻辑是根据操作符id读取示例代码,并使用markdown view渲染。
public class SampleCodePlugin implements DisplayPluginManager.Plugin {
@Override
public Tuple.Tuple2<Observable<View>, View> getView(final Context context, String key) {
// 创建Markdown view,使用weakreference,为了处理嵌入式touch事件的处理冲突,还需要重写其
onTeouchEvent方法。
MarkdownView markdownView = new MarkdownView(context){
@Override
public boolean onTouchEvent(MotionEvent event) {
requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(event);
}
};
markdownView.setBackgroundColor(Color.LTGRAY);
final Reference<MarkdownView> ref = new WeakReference<>(markdownView);
Observable<View> o = Observable.just(key)
// .observeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String s) {
// 根据id获取示例代码,示例代码已经提前生成。
return mSampleCode.get(s);
}
})
.observeOn(Schedulers.from(UIThreadExecutor.SINGLETON))
.map(new Func1<String, View>() {
@Override
public View call(String s) {
// 使用markdownview加载示例代码
MarkdownView mv = ref.get();
if (mv != null) {
mv.loadMarkdown(s);
}
return mv;
}
});
return new Tuple.Tuple2<>(o, (View) markdownView);
}
根据操作符切换
每当点击操作符之后,界面更新的同时,程序也会执行该操作符对应的示例代码,并将示例代码结果输出到界面,输出的形式是重定向日志的方式,即将程序输出结果逐行append到结果输出界面。
四、项目结构
如上图,为整个demo工程的项目结构截图,为一个通用的android项目结构图,其中的
README.md:为Rxjava及部分项目的介绍。
*.py文件:为自动生成marble图及示例代码的脚本。
五、其他
本示例从逻辑到实现概要介绍如上,详细内容,请参考demo源码。
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
RxJava API使用示例的更多相关文章
- ASP.NET Web API 开篇示例介绍
ASP.NET Web API 开篇示例介绍 ASP.NET Web API 对于我这个初学者来说ASP.NET Web API这个框架很陌生又熟悉着. 陌生的是ASP.NET Web API是一个全 ...
- 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1
老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例 在上一节的第一个“增加日记”的示例中,我们并没有看到日记是否真的增加成功 ...
- 老李推荐: 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例
老李推荐: 第3章1节<MonkeyRunner源码剖析>脚本编写示例: MonkeyRunner API使用示例 MonkeyRunner这个类可以说是编写monkeyrunner脚 ...
- HTML 百度地图API调用示例源码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Jedis API 详细示例
Jedis API 详细示例 https://www.jianshu.com/p/125357ee7651
- Java8新特性时间日期库DateTime API及示例
Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...
- 实验6、Flask API使用示例和拓展
实验介绍 1. 实验内容 Flask 提供了多种API拓展,本节我们主要学习基于RESTful的Flask应用程序设计 2. 实验要点 学习和掌握多种RESTful的设计模式 3.实验环境 Cento ...
- SharePoint 2013 Search REST API 使用示例
前言:在SharePoint2013中,提供Search REST service搜索服务,你可以在自己的客户端搜索方法或者移动应用程序中使用,该服务支持REST web request.你可以使用K ...
- ASP.NET Web API 入门示例详解
REST服务已经成为最新的服务端开发趋势,ASP.NET Web API即为.NET平台的一种轻量级REST架构. ASP.NET Web API直接借鉴了ASP.NET MVC的设计,两者具有非常类 ...
随机推荐
- UML功能模型(用例图)
在UML系统开发中有三个主要的模型:功能模型(从用户角度展示系统的功能,包括用例图).对象模型(采用对象,属性,操作关联等概念展示系统的结构和基础,包括类图.对象图.包图).动态模型(展示系统 ...
- POJ1067 取石子游戏 威佐夫博弈 博弈论
http://poj.org/problem?id=1067 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可 ...
- 「PKUSC2018」星际穿越 (70分做法)
5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 27 Solved: 11[Submit][Status] ...
- BZOJ 4883 [Lydsy2017年5月月赛]棋盘上的守卫(最小生成环套树森林)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4883 [题目大意] 在一个n*m的棋盘上要放置若干个守卫. 对于n行来说,每行必须恰好 ...
- GCDAsyncSocket类库,IOS下TCP通讯使用心得
关于在IOS下使用Socket进行通讯的技术文章也许诺很久了,今日又是一个还债的日子,网上虽然很多介绍过AsyncSocket或GCDAsyncSocket的文章,但其实就那么一两篇大部分都是转载,于 ...
- NOIP2014 解题报告·水渣记
Day 1: 第一次参加noip.小激动,小紧张,这些正常的情绪就不用说了.唯一值得一提的是 我早上步行去郑大工学院的时候迷路了,直接转进了隔壁的河南农大,绕了半天找不到机房,还给几个同学打了电话可就 ...
- 测试 markdown
PHP 标量类型与返回值类型声明 标量类型声明 默认情况下,所有的PHP文件都处于弱类型校验模式. PHP 7 增加了标量类型声明的特性,标量类型声明有两种模式: 强制模式 (默认) 严格模式 标量类 ...
- HDU 5294 Tricks Device 网络流 最短路
Tricks Device 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5294 Description Innocent Wu follows D ...
- Web安全测试指南--权限管理
垂直权限提升: 编号 Web_Author_01 用例名称 垂直权限提升测试 用例描述 测试用户是否具有使用超越其角色范围之外的权限. 严重级别 高 前置条件 1. 目标系统拥有不同等级的角色和权限 ...
- java访问ad域
1.活动目录(AD) Active Directory 是用于 Windows Server 的目录服务.它存储着网络上各种对象的有关信息,并使该信息易于管理员和用户查找及使用.Active Dire ...