• RxJava API使用示例


    概述

    RxJava API示例代码,可离线查看rxjava1.0大部分API的marble图,描述,示例代码,并支持示例代码实时输出及展示执行结果。

    详细

    一、项目概述

    本Demo是为了方便大家了解RxJava的API,我将所有的RxJava API(至少是官方文档中提到的)都写在一个android apk中,并在其中附以功能描述,代码示例,marble-diagram(Rx用来描述数据及其处理流程的图), 以及一些使用场景. 所有的资料都是在APK中,使用的时候不会消耗任何流量,而且你可以在任何时候任何地方学习使用.

    示例程序的特点如下:

    1. API涵盖全面: 包含了核心库及所有扩展实现库200个左右的API.

    2. 数据本地化,无需流量: 示例中的所有数据和图片都是本地加载的,所以无需消耗流量.

    3. 示例代码都是从源码中直接生成,所以看起来跟代码直接运行的效果是一样的

    二、主界面展示

    rxjava-1.pngrxjava-2.png

    上图为整个Demo的运行示例截图:

    1. 左边为Rxjava主要组件及运算符类别入口

    2. 右边为单个运算符的marble-diagram, 详细的运算符列表,代码示例以及代码的执行结果。

    3. 点击相应的运算符,界面会切换到该运算符的marble-diagram以及示例代码,同时会执行该代码,将执行结果输出到结果区。

    三、代码实现

    在整个Demo中,主要部分就是RxJava API运算子的呈现,包括marble图,API描述,示例代码,运算结果的展现

    及不同运算子切换的交互。

    所有的UI组成部分都是以插件的形式插入到Demo的UI体系中,设计图如下:

    1515889126069018826.png

    APIBaseActivity: API详情主Activity,包含了重定向输出结果到结果view以及整合DisplayPluginManager中所有View的展示的功能。

    DisplayPluginManager: 管理所有的展示Plugin。

    Plugin: 展示Plugin的接口类,主要负责根据不同的操作符ID提供不同的插件View。

    MarbleDiagramPlugin: Marble图展示插件。

    DescriptionPlugin: API描述展示插件。

    SampleCodePlugin: 示例代码展示插件。

    下边详细介绍这四部分的核心实现:

    Marble图

    marble图的地址是我在看官方文档的时候,手动扣取的,所有地址都保存在项目的MarbleDiagramPlugin.java中

    1515884850352091921.png

    最初demo使用的是动态获取marble图地址,由于原图需要消耗流量且图片较大,所以我是将所有图片从网络拉取到本地直接打包到apk中,而且在这个过程中对图片进行了进一步的打包压缩。

    1. 读取marble地址配置

    # 将原来的注册地址的代码块处理并读取出来
    def ProcessRegisterBlock(lines):
      if len(lines) == 0:
        return None
      mb = []
      for line in lines:
        line = line.strip('
     ,);')
        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 = '
    add(%s,%s);' % (key, code0)
    elif len(code) == 2:
      code0 = Url2Id(code[0])
      code1 = Url2Id(code[1])
      s = '
    add(%s,%s,%s);' % (key, code0, code1)
    elif len(code) == 3:
      code0 = Url2Id(code[0])
      code1 = Url2Id(code[1])
      code2 = Url2Id(code[2])
      s = '
    add(%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 = '
    add(%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到结果输出界面。

    四、项目结构

    image.png

    如上图,为整个demo工程的项目结构截图,为一个通用的android项目结构图,其中的

    README.md:为Rxjava及部分项目的介绍。

    *.py文件:为自动生成marble图及示例代码的脚本。

    五、其他

    本示例从逻辑到实现概要介绍如上,详细内容,请参考demo源码。

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    问题 B: 投简历
    问题 C: P4 游戏中的Human角色
    绘制直方图
    绘制条形图
    绘制散点图
    问题 A: E2 驾驭const
    问题 B: 矩形类中运算符重载【C++】
    extjs tips
    extjs
    struts1
  • 原文地址:https://www.cnblogs.com/demodashi/p/8491168.html
Copyright © 2020-2023  润新知