RxJava API使用示例

概述

RxJava API示例代碼,可離線查看rxjava1.0大部分API的marble圖,描述,示例代碼,並支持示例代碼實時輸出及展現執行結果。

詳細

1、項目概述

本Demo是爲了方便你們瞭解RxJava的API,我將全部的RxJava API(至少是官方文檔中提到的)都寫在一個android apk中,並在其中附以功能描述,代碼示例,marble-diagram(Rx用來描述數據及其處理流程的圖), 以及一些使用場景. 全部的資料都是在APK中,使用的時候不會消耗任何流量,並且你能夠在任什麼時候候任何地方學習使用.html

示例程序的特色以下:java

1. API涵蓋全面: 包含了核心庫及全部擴展實現庫200個左右的API.python

2. 數據本地化,無需流量: 示例中的全部數據和圖片都是本地加載的,因此無需消耗流量.android

3. 示例代碼都是從源碼中直接生成,因此看起來跟代碼直接運行的效果是同樣的markdown

2、主界面展現

rxjava-1.pngrxjava-2.png

上圖爲整個Demo的運行示例截圖:網絡

  1. 左邊爲Rxjava主要組件及運算符類別入口app

  2. 右邊爲單個運算符的marble-diagram, 詳細的運算符列表,代碼示例以及代碼的執行結果。ide

  3. 點擊相應的運算符,界面會切換到該運算符的marble-diagram以及示例代碼,同時會執行該代碼,將執行結果輸出到結果區。性能

3、代碼實現

在整個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('\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到結果輸出界面。

4、項目結構

image.png

如上圖,爲整個demo工程的項目結構截圖,爲一個通用的android項目結構圖,其中的

README.md:爲Rxjava及部分項目的介紹。

*.py文件:爲自動生成marble圖及示例代碼的腳本。

5、其餘

本示例從邏輯到實現概要介紹如上,詳細內容,請參考demo源碼。

 

 

注:本文著做權歸做者,由demo大師發表,拒絕轉載,轉載須要做者受權

相關文章
相關標籤/搜索