精华内容
下载资源
问答
  • redex

    2018-04-24 02:42:54
    redex基本用法Storestore是保存数据的地方,它是整个应用的容器,整个应用只能有一个store。redux提供了createStore来生成store import {createStore} from 'redux';const store = createStore(fn); //createStore...

    redex基本用法

    Store

    store是保存数据的地方,它是整个应用的容器,整个应用只能有一个store。

    redux提供了createStore来生成store

     import {createStore} from 'redux';const store = createStore(fn); //createStore接收另一个函数为参数,生成一个新的store对象复制代码

    State

    state对象包含整个应用的数据,在应用中可以使用store.getState()得到。

     const state = store.getState(); //这里一个state对应一个view,只要state相同,view就相同复制代码

    Action

    在应用中state的变化会导致view的变化,但是对于用户而言是接触不到state,只能接触到view。所以state的变化必须由view导致的,action的作用就是通知state发生变化的渠道。action是一个对象,type是它的名字,是必须的。

     const action = {  type: 'ADD_LIST', //名称  payload: 'str' //荷载}复制代码

    Action Creator

    从以上的介绍当中发现,view要发送多少种消息就要创建多少个action,现在我们用一个工厂函数来生成Action,即Action Creator。

     const ADD_LIST = '添加列表'function addList(text) { //addLista函数就是一个Action Creator  type: ADD_LIST,  text}const action = addList('template 1')复制代码

    store.dispatch()

    store.dispatch()是view发出action的唯一方法。

     store.dispatch({ //接收一个action对象作为参数,将它发送出去  type: 'ADD_List',  payload: 'templata 1'});//结合Action Creator的写法,可以写为下列形式store.dispatch(addList('template 1'))复制代码

    Reducer

    store接收到action之后,必须给出一个新的state,这样view才会发生变化,这种state的计算过程叫做reducer。reducer是一个函数,它接收action和当前的state作为参数,返回一个新的state。

     const reducer = function (state,action) {  //...  return new_state;}复制代码

    用下面的实例来解释

     const defaultState = 0;const reducer = (state = defaultState, action) => {  Switch (action.type) {    case 'ADD':        return state + action.payload;    default        return state;  }}const state = reducer(1,{  type: 'ADD',  payload: 1})复制代码

    在实际的应用当中我们并不用像这样的手动调用,运用store.dispatch方法会触发reducer的自动执行。所以,store在创建的时候,就要将reducer传入createStore中。

     import { createStore } from 'redux';const store = createStore(reducer);复制代码

    reducer不能改state,只能返回一个全新的state

     // State 是一个对象function reducer(state, action) {  return Object.assign({}, state, { thingToChange });  // 或者  return { ...state, ...newState };}​// State 是一个数组function reducer(state, action) {  return [...state, newItem];}复制代码

    store.subscribe()

    store允许使用store.subscribe方法设置监听函数,一旦state发生了变化,就执行这个函数。

     store.subscribe(listener);复制代码

    简单的说在创建应用的时候,只要把render和setState放入listen中,就会实现view的自动渲染,store.subscribe()返回一个函数,调用这个函数可以解除监听。

     let unsubscribe = store.subscribe(()=>{  //...})unsubscribe();复制代码

    Store 的实现

    在store中有三个方法,分别是

    • store.getState()

    • store.dispatch()

    • store.subscribe()

     import {createStore} from 'redux'let { subscribe, dispatch, getState } = createStore(reducer);复制代码

    createStore方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。

     let store = createStore(todoApp, window.STATE_FROM_SERVER)复制代码

    下面用实例来解释下store是如何生成的

     const createStore = (reducer) = {  let state;  let listeners = [];  const getState = () => state;  const dispatch = (action) => {    state = reducer(state, action);    listeners.forEach(listener => listener());  } const subscribe = (listener) => {    listeners.push(listener);    return () => {      listeners = listeners.filter(l => l !== listener);    }  };​  dispatch({});​  return { getState, dispatch, subscribe };}复制代码

    Reducer 的拆分

    Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大。

     const chatReducer = (state = defaultState, action = {}) => {  const { type, payload } = action;  switch (type) {    case ADD_CHAT:      return Object.assign({}, state, {        chatLog: state.chatLog.concat(payload)      });    case CHANGE_STATUS:      return Object.assign({}, state, {        statusMessage: payload      });    case CHANGE_USERNAME:      return Object.assign({}, state, {        userName: payload      });    default: return state;  }};复制代码

    下面我们将redecer进行拆分(一个react根组件可以由很多子组件构成)

    const chatReducer = (state = defaultState, action = {}) => {
      return {
        chatLog: chatLog(state.chatLog, action),
        statusMessage: statusMessage(state.statusMessage, action),
        userName: userName(state.userName, action)
      }
    };复制代码

    redux提供了一个combineReducers方法用于reducer的拆分。

     import { combineReducers } from 'redux';const chatReducer = combineReducers({  chatLog,  statusMessage,  userName})​export default todoApp;复制代码

    在实际的项目当中,你可以把reducer放在一个文件里面,然后统一的引入。

     import { combineReducers } from 'redux'import * as reducers from './reducers'const reducer = combineReducers(reducers)复制代码

    工作流程


    首先用户发出action

     store.dispatch(action)复制代码

    然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。

     let nextState = todoApp(previousState, action);复制代码

    State 一旦有变化,Store 就会调用监听函数。

     // 设置监听函数store.subscribe(listener);复制代码

    listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。

     function listerner() {  let newState = store.getState();  component.setState(newState);   }复制代码

    实例应用

     const Counter = ({ value }) => (  <h1>{value}</h1>);const render = () => {  ReactDOM.render(    <Counter value={store.getState()}/>,    document.getElementById('root')  );};​store.subscribe(render);render();复制代码

    上面是一个简单的计数器,唯一的作用就是把参数value的值,显示在网页上。Store 的监听函数设置为render,每次 State 的变化都会导致网页重新渲染。

    下面加入一点变化,为Counter添加递增和递减的 Action。

     const Counter = ({ value, onIncrement, onDecrement }) => (  <div>  <h1>{value}</h1>  <button onClick={onIncrement}>+</button>  <button onClick={onDecrement}>-</button>  </div>);​const reducer = (state = 0, action) => {  switch (action.type) {    case 'INCREMENT': return state + 1;    case 'DECREMENT': return state - 1;    default: return state;  }};​const store = createStore(reducer);​const render = () => {  ReactDOM.render(    <Counter      value={store.getState()}      onIncrement={() => store.dispatch({type: 'INCREMENT'})}      onDecrement={() => store.dispatch({type: 'DECREMENT'})}    />,    document.getElementById('root')  );};​render();store.subscribe(render);复制代码


    展开全文
  • redex是android字节码(dex)优化器,最初在
  • Redex synth example

    2021-01-12 15:13:33
    <div><p>This PR illustrates one of the synth wrapper removal ...- A Makefile for running Redex on the APK generated by Android studio.</p><p>该提问来源于开源项目:facebook/redex</p></div>
  • 1 redex-all 0x000000010330d563 _ZNK9irtc_impl13TypeInference19analyze_instructionEP13IRInstructionP34PatriciaTreeMapAbstractEnvironmentIj20FiniteAbstractDomainI6IRType16BitVectorLatticeIS5_Lm16ENSt3__...
  • Add Redex to Homebrew

    2021-01-12 15:16:30
    <div><p>For convenience, it would be nice to simply do: <p><code>brew install redex</code></p>该提问来源于开源项目:facebook/redex</p></div>
  • Redex 集成踩坑

    2019-08-07 19:52:52
    一. 配置环境(MacOS) xcode-select --install brew install autoconf automake libtool python3 brew install boost jsoncpp ...二. 安装Redex ...方式一: Homebrew 有直接可体验...brew install redex 方式...

    一. 配置环境(MacOS)

    xcode-select --install

    brew install autoconf automake libtool python3

    brew install boost jsoncpp

     

    二. 安装Redex

    方式一: Homebrew 有直接可体验版本,但比较老,不支持D8编译器产生的APK

    brew install redex

     

    方式二: Clone源码编译最新版本,支持D8编译器

    1)git clone https://github.com/facebook/redex.git

     

    2)安装老版本的boost, 最新版本1.70有bug,导致源码编译失败,看issue描述boost会在1.71版本修复这个bug。 1.70以后的releaes版本应该不需要安装旧版本了

     

    PS:不要用brew install boost@1.69这种带版本号的方式安装其他版本,会导致环境路径有误,编译还是会出错。

     

    brew uninstall boost

    brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/b4de2e1ce084ec249ca61c3eff6f96617e38c081/Formula/boost.rb

     

    3)编译源码

    cd redex

    autoreconf -ivf && ./configure && make

     

    4)如果之前通过homebrew安装过redex,先卸载

    brew uninstall redex

    然后

    sudo make install

     

    至此,Redex应该是正确安装了。

     

    三. 使用

    1. 源码中的/config文件夹下有两个配置,可以使用defalut.config来使用一下Redex

     

    redex /path/to/apk/ -c default.config -o path/to/output/apk/

     

    2. 如果处理的是proguard过的apk,需要在配置文件中配置proguard的mapping文件,帮助redex识别混淆的代码

     

    "proguard_map":"/Path/to/proguard_mapping_release.txt"

     

    3. 可以通过-P指定一个Proguard rule, 使Redex遵循Prouard的rule防止误删类

    -P common.cfg

     

    4. 如果执行时有报错,可以根据实际情况修改default.config中的passes节点,关闭导致错误的pass配置

     

    5. 经过Redex处理过的apk需要重新签名

    1)简单debug自动签名可用--sign处理,不然无法安装

    2)用-s 指定keystore文件 -s path/to/android/keystore --sign

    展开全文
  • You can re-run it under gdb by running /tmp/redex.kemIzp/redex-gdb-6srz5hg7.sh or under lldb by running /tmp/redex.kemIzp/redex-lldb-wxvpt36n.sh</p><p>该提问来源于开源项目:facebook/redex</p></...
  • You can re-run it under gdb by running /tmp/redex.zJbATc/redex-gdb-T8cTka.sh or under lldb by running /tmp/redex.zJbATc/redex-lldb-g0jtUB.sh </module></code></pre> <p>Is it somehow related to ...
  • <div><p>Trying to install redexed app fails with <code>Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES] Tried with both debug & release apk.</p><p>该提问来源于开源项目:...facebook/redex</p></div>
  • redex: command not found

    2021-01-12 15:20:01
    I installed and compiled according to this document, but the prompt “-bash: redex: command not found” The following is my installation steps: <p>1 <code>xcode-select--install</code> 2<code>...
  • <div><p>Make sure we can reliably build and support ReDex for Windows 10. One approach might be to use the new native support for bash as suggested by in #17 </p><p>该提问来源于开源项目:...
  • Redex踩坑记

    2017-01-20 18:00:30
    Redex踩坑全集第一步 安装Redex以下内容基本来自https://github.com/facebook/redex 1. 安装以下前置条件 sudo apt-get install \ g++ \ automake \ autoconf \ autoconf-archive \ libtool \ libboost-all-...

    Redex踩坑全集

    第一步 安装Redex

    以下内容基本来自https://github.com/facebook/redex
    1. 安装以下前置条件

    
     sudo apt-get install \
        g++ \
        automake \
        autoconf \
        autoconf-archive \
        libtool \
        libboost-all-dev \
        liblz4-dev \
        liblzma-dev \
        make \
        zlib1g-dev \
        binutils-dev \
        libjemalloc-dev \
        libiberty-dev \
        libjsoncpp-dev
    1. clone Redex源码到本地,编译合安装
    git clone https://github.com/facebook/redex.git
    
    //进入redex目录
    cd redex
    
    //编译 安装
    autoreconf -ivf && ./configure && make
    sudo make install
    
    1. 使用
    redex input.apk -o output.apk //output.apk就是你的产物咯

    填坑

    1. 找不到zipalign
    Couldn't find zipalign. See README.md to resolve this

    解决方案:
    添加zipalign到环境变量

    //添加zipaligin到环境变量 sdk/build-tool/xxx
    sudo vim /etv/profile
    export ZIP_HOME=xxxx
    PATH=...:$ZIP_HOME
    //刷新一下,让配置在窗口实时生效
    source /etc/profile

    2.安装提示没有签名(因为修改了dex,所以必修要手动重新签名) <以及4.4以下手机按照官网提示,重新签名之后仍不好使,
    下面的命令可以搞定>

    Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
    //强大的
     jarsigner  -digestalg SHA1 -sigalg MD5withRSA  -tsa https://timestamp.geotrust.com/tsa  -verbose -keystore ts_hz -signedjar output.apk(输入) input.apk(输入) alias(签名的alias)
    展开全文
  • <div><p>App crashes on launch. <pre><code> java.lang.IllegalAccessError: Illegal class access: '... attempting to access 'io.fabric.sdk.android.services.common....facebook/redex</p></div>
  • <div><p>Running redex.py with default config from the config/default.config produces a crash: <code>./redex.py app-debug.apk -c config/default.config Using config config/default.config Using binary ...
  • <div><p>I am trying to run redex on multidex app. It has two dex: classes.dex(primary) and classes1.dex When I run redex on my app, app crashed with NoClassDefFoundError . I noticed app is crashing ...
  • ReDex 是 Facebook 开发的一个 Android 字节码的优化工具。它提供了 .dex 文件的读写和分析框架,并提供一组优化策略来提升字节码。使用方法很简单: redex path/to/your.apk -o path/to/output.apk输出后的 output....
  • <div><p>Running redex on my app encounters this issue. <p><code>redex app.apk -o tiko.apk</code></p> <pre><code> libredex/IRTypeChecker.cpp:388: void irtc_impl::TypeInference::analyze_instruction...
  • Redex安卓Apk优化技术研究

    千次阅读 2017-02-28 21:48:24
    Redex介绍ReDex 是 Facebook 开源的工具,通过对字节码进行优化,以减小 Android Apk 大小,同时提高 App 启动速度。 GitHub:ReDex github,官网主页:fbredex.com本次研究完成了Redex在Ubuntu linux上的安装和...

    Redex介绍

    ReDex 是 Facebook 开源的工具,通过对字节码进行优化,以减小 Android Apk 大小,同时提高 App 启动速度。
    GitHub:ReDex github,官网主页:fbredex.com

    本次研究完成了Redex在Ubuntu linux上的安装和配置,以卡包App为例进行了Redex优化测试, 实验了Redex优化的主要流程, 包括Inderdex。

    Redex优化的基础知识

    可以先看看这几篇文章:
    * 基于 Facebook Redex 实现 Android APK 的压缩和优化
    * Facebook App 优化工具 ReDex 优化的 6 点及未优化的一大方面
    * Optimizing Android bytecode with ReDex

    Ubuntu上安装Redex

    Redex目前支持Ubuntu Linux和Mac系统, 安装时需要编译源码,Ubuntu下面需要有sudo权限才能安装。
    安装过程参考官方文档。

    Ubuntu 14.04 LTS (64-bit)

    sudo apt-get install \
        g++ \
        automake \
        autoconf \
        autoconf-archive \
        libtool \
        libboost-all-dev \
        liblz4-dev \
        liblzma-dev \
        make \
        zlib1g-dev \
        binutils-dev \
        libjemalloc-dev \
        libiberty-dev \
        libjsoncpp-dev

    Download, Build and Install

    Get ReDex from GitHub:

    git clone https://github.com/facebook/redex.git
    cd redex

    Now, build ReDex using autoconf and make.

    autoreconf -ivf && ./configure && make
    sudo make install

    然后就可以在命令行下运行Redex了

    Redex Indexdex介绍

    Interdex优化比较复杂,默认配置是不开启的,具体看Interdex文档
    Interdex Pass 可以优化dex中class的顺序,以及class在不同的dex中的分布(如果是app使用了multidex)
    按照class在实际运行中调用的顺序在dex中进行重新排序,可以带来几个好处:
    - 更少的IO
    - 更少的内存占用
    - 更少page cache污染

    Redex默认的配置文件是不包含Inderdex这一步的。增加Inderdex后的配置文件如下:

    {
    "redex" : {
    "passes" : [
    "ReBindRefsPass",
    "BridgePass",
    "SynthPass",
    "FinalInlinePass",
    "DelSuperPass",
    "SingleImplPass",
    "SimpleInlinePass",
    "StaticReloPass",
    "RemoveEmptyClassesPass",
    "ShortenSrcStringsPass",
    "InterDexPass"
    ],
    "coldstart_classes":"app_list_of_classes.txt" //class调用顺序列表
    }
    }

    生成输入数据

    如何得到实际运行中class的调用顺序?

    首先需要收集app的运行数据

    按照典型使用场景操作app,获取heap dump文件, 使用redex提供的脚本redex/tools/hprof/dump_classes_from_hprof.py分析dump文件,得到class列表。
    这里有个坑,首先是dump_classes_from_hprof.py在python2运行都有错误, Python2需要安装enum34后才能正常运行, 不兼容python3
    在ubuntu上安装enum34后,用python2.7运行,可以得到class列表

    具体操作过程如下

    // get the process if of your app

    adb shell ps | grep YOUR_APP_NAME | awk '{print $2}' > YOUR_PID ( if you don't have awk, the second value is the pid of your app)

    // dump the heap of your app. You WILL NEED ROOT for this step

    adb root
    adb shell am dumpheap YOUR_PID /data/local/tmp/SOMEDUMP.hprof

    // copy the heap to your host computer

    adb pull /data/local/tmp/SOMEDUMP.hprof YOUR_DIR_HERE/.

    // pass the heap dump to the python script for parsing and printing out the class list
    // Note that the script needs python 2

    YOUR_PYTHON_2_PATH redex/tools/hprof/dump_classes_from_hprof.py --hprof YOUR_DIR_HERE/SOMEDUMP.hprof > list_of_classes.txt

    测量优化效果

    主要是看app内存占用和 .dex mmap

    adb shell ps | grep com.test.app | awk '{ print $2 }'
    9003
    
    [R:\AndroidM\packages\apps]$ adb shell dumpsys meminfo 9003
    Applications Memory Usage (kB):
    Uptime: 2329984 Realtime: 2329984
    
    ** MEMINFO in pid 9003 [com.test.app] **
                       Pss  Private  Private  Swapped     Heap     Heap     Heap
                     Total    Dirty    Clean    Dirty     Size    Alloc     Free
                    ------   ------   ------   ------   ------   ------   ------
      Native Heap    10711    10044        0        0    44416    40455     3960
      Dalvik Heap     2201     2172        0        0    35719    33937     1782
     Dalvik Other     5424     4984        0        0                           
            Stack      516      516        0        0                           
           Ashmem        4        0        0        0                           
        Other dev        5        0        4        0                           
         .so mmap      967      152      148      360                           
        .apk mmap      271        0       56        0                           
        .ttf mmap        8        0        0        0                           
        .dex mmap     4531        8     4464        0                           
        .oat mmap     2274        0      776        0                           
        .art mmap     2761     1352     1020        0                           
       Other mmap       94        8        8        0                           
        GL mtrack     4196     4196        0        0                           
          Unknown      190      188        0        0                           
            TOTAL    34153    23620     6476      360    80135    74392     5742
    
     App Summary
                           Pss(KB)
                            ------
               Java Heap:     4544
             Native Heap:    10044
                    Code:     5604
                   Stack:      516
                Graphics:     4196
           Private Other:     5192
                  System:     4057
    
                   TOTAL:    34153      TOTAL SWAP (KB):      360
    
     Objects
                   Views:       48         ViewRootImpl:        0
             AppContexts:        2           Activities:        1
                  Assets:        3        AssetManagers:        2
           Local Binders:       12        Proxy Binders:       27
           Parcel memory:       13         Parcel count:       52
        Death Recipients:        0      OpenSSL Sockets:        0
    
     SQL
             MEMORY_USED:      663
      PAGECACHE_OVERFLOW:       88          MALLOC_SIZE:       62
    
     DATABASES
          pgsz     dbsz   Lookaside(b)          cache  Dbname
             4       68            512      225/36/22  /data/user/0/com.test.app/databases/MyTicket
    

    App冷启动时间测试

    我们常说的App冷启动,是指启动时你的应用程序的进程是没有创建的. 这也是大部分应用的使用场景.用户在桌面上点击你应用的 icon 之后,首先要创建进程,然后才启动 MainActivity.
    这时候adb shell am start -W packagename/MainActivity 返回的结果,就是标准的应用程序的启动时间(注意 Android 5.0 之前的手机是没有 WaitTime 这个值的)
    具体可以参考怎么计算apk的启动时间?
    如果只关心某个应用自身启动耗时,参考TotalTime;如果关心系统启动应用耗时,参考WaitTime;如果关心应用有界面Activity启动耗时,参考ThisTime。

    我编写了一个python脚本,可以自动进行多次冷启动,并画出启动时间统计图,计算平均启动时间。用这个脚本可以很方便的测量任意app的启动时间。
    打开app,马上运行adb shell dumpsys activity top,可以看到app的包名和启动Activity, 测试脚本需要输入包名和启动activity的完整类名。

    Redex优化效果分析

    使用以前开发的App做测试,体积20M,使用了multidex。由于app有启动页,本身启动速度已经很快,1s多一点,因此优化效果不够明显。

    优化前数据
    ['465', '1122', '1163']
    [['444', '1123', '1149'], ['440', '1150', '1191'], ['410', '1450', '1520'], ['439', '1081', '1112'], ['419', '1072', '1117'], ['409', '1055', '1084'], ['423', '1101', '1135'], ['427', '1079', '1120'], ['465', '1122', '1163']]
    apk launcher avarage times:[ThisTime, TotalTime, WaitTime]
    [  430.66665649  1137.          1176.77783203]
    
    redex优化后的数据,优化后TotalTime减少70ms
    ['453', '1129', '1159']
    [['403', '1072', '1099'], ['411', '1077', '1123'], ['414', '1056', '1085'], ['383', '1031', '1077'], ['386', '1056', '1102'], ['381', '1030', '1071'], ['449', '1111', '1148'], ['390', '1095', '1127'], ['453', '1129', '1159']]
    apk launcher avarage times:[ThisTime, TotalTime, WaitTime]
    [  407.777771    1073.          1110.11108398]
    

    结论

    Redex可以在Proguard优化后再在dex层面进行优化,Redex需要配置Proguard配置文件来保护一些不应该被优化的类(如JNI调用、反射调用的类等)。
    根据实际测试结果看Redex优化后可以提升冷启动速度10%左右,apk体积减少100k左右,低于Facebook给出的数据(25%)。原因可能是我测试的Apk比较简单,本身启动速度已经比较快,后面应该找启动速度慢的App进行优化测试。
    普通App建议在做了Proguard优化后,再根据冷启动测试数据决定是否做Redex优化。

    参考文章

    ReDex github
    Optimizing Android bytecode with ReDex
    基于 Facebook Redex 实现 Android APK 的压缩和优化
    Facebook App 优化工具 ReDex 优化的 6 点及未优化的一大方面

    浅谈Android启动时间
    怎么计算apk的启动时间?

    展开全文
  • <div><p>We noticed a huge spike in crash-rate for our first launch with the redex optimized apk. We are still investigating the root cause, but I wanted to know if you guys have seen this before / or ...
  • /tmp/redex.671dOS/redex-all --apkdir /tmp/redex.671dOS/tmp2a3KIk.redex_extracted_apk --outdir /tmp/redex.671dOS/tmpBJcKPV.redex_dexen /tmp/redex.671dOS/tmpBJcKPV.redex_dexen/dex0/classes.dex /tmp/...
  • 法国REDEX双驱消隙减速机-参数pdf,法国REDEX双驱消隙减速机-参数
  • Facebook 出品的 apk 包优化工具 redex.zip,A bytecode optimizer for Android apps
  • ReDex: An Android Bytecode Optimizer ReDex is an Android bytecode (dex) optimizer originally developed at Facebook. It provides a framework for reading, writing, and analyzing .dex files, and a set of...
  • <div><p>Create an option to generate ReDex binaries with dependencies statically linked. Statically linked libraries will reduce the overhead of installing dependencies like Boost, JsonCpp & LibZ...
  • <div><p>https://source.android.com/security/apksigning/v2.html is enabled by default from android gradle plugin 2.2.0 onwards.</p> <p>v2 signed Gradle built apks will fail to ...facebook/redex</p></div>
  • <div><p>Is there any way to get a gradle plugin to make redex widely used ?</p><p>该提问来源于开源项目:facebook/redex</p></div>

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 303
精华内容 121
关键字:

ReDex