范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

RN原生模块和组件入门

  前段时间,由于业务的需求,开始接触到了 RN 原生模块和组件的开发,最近刚好有一位同事也是有这方面的需求要开发就过来问我,我一时间竟然有点说不清楚,回想一下,挺多一些点已经有些模糊了,趁着现在刚过完年回来,需求还不多的时候,按照官方的文档又重新理了一遍。原生模块
  我们做 RN 需求的过程,有时候需要拿一些硬件方面的数据,比如蓝牙、NFC,又或者人脸、指纹等数据,这些可能还会有些第三方库做这些东西,但是像我们自己业务的一些用户体系的一些数据,我们需要一套规范的 API ,这个时候就是原生模块上场的时机,我们可以定义一套获取用户体系的 API 接口,并且加上一些控制的逻辑来方便和规范 RN 的调用。
  下面就以官方的例子来说明如何接入 原生模块 吧。 ReactContextBaseJavaModule
  首先我们需要一个 Module ,我们后面在 RN 调用的这个模块的方法就来自这个类。我们先创建一个类,继承  ReactContextBaseJavaModule  。public class CalendarModule extends ReactContextBaseJavaModule {    CalendarModule(ReactApplicationContext context) {        super(context);    } } getName()
  ReactContextBaseJavaModule  这个类是一个抽象类,但是只需要实现一个方法。String getName();
  getName()  这个方法会返回一个 String  这个就是我们模块的名称了。@Override public String getName() {    return "CalendarModule"; }
  实现之后,我们后面就可以像下面这样在 RN 中调用这个模块了。 const { CalendarModule } = ReactNative.NativeModules;
  或者,下面这样也可以拿到这个模块对象。 const CalendarModule = NativeModules.CalendarModule
  其实这两种方法本质是一样的,只是第一种方式是用了解构赋值的语法。 @ReactMethod
  对于想要暴露出去的方法,只需要在方法的上面添加  @ReactMethod  这个注解就可以了,但是要记得方法的访问权限是 public  的。@ReactMethod public void createCalendarEvent(String name, String location) { }
  还有一点要注意,RN 调用原生模块的时候是异步的,也就是说,调用之后就会走 RN 的后续逻辑,并不会等待原生代码执行完成。 @ReactMethod(isBlockingSynchronousMethod = true)
  刚才说到一般的 RN 调用是异步的,如果有同步调用的需求,可以在  @ReactMethod  这个注解里面添加 isBlockingSynchronousMethod = true  这个参数,这样的话,调用过程就是同步的了。
  但是官方不是很建议我们使用这个,主要还是考虑到有些开发者会误用,导致性能问题,或者造成线程相关的bug。
  另外,如果使用同步调用这种方式,就无法使用 Chrome 进行 debug 了。 注册模块
  Module 写完了,但是现在 RN 还不能调用,因为还需要一个注册的过程。 ReactPackage
  注册需要使用到 ReactPackage ,因为有时候我们可能会有好几个 Module ,需要我们把 Module 打包进 ReactPackage 里面,然后再进行注册。在 RN 初始化的阶段,会扫描所有注册进来的 ReactPackage ,并进行初始化。
  同样的,我们需要一个类,实现 ReactPackage 。然后在  createNativeModules()  里面返回含有 ReactContextBaseJavaModule  的集合。public class MyAppPackage implements ReactPackage {     @Override    public List createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }     @Override    public List createNativeModules(            ReactApplicationContext reactContext) {        List modules = new ArrayList<>();         modules.add(new CalendarModule(reactContext));         return modules;    }  }
  如果你细心的话,还会发现有个  createViewManagers()  的方法,这个是用来返回 原生组件 的,后面再讲。ReactNativeHost
  现在我们  ReactNativePage  包也有了,就只剩最后一个问题了。如何注册?
  其实也很简单,我们首先要找到  ReactNativeHost  ,你可以简单理解为 RN 的容器,就像 Android 的 Activity  和 iOS 的 View Controller 。如果你是用 RN 默认的构建脚本创建的项目,ReactNativeHost  一般是 MainApplication.java  这个文件。
  找到之后就简单了。只需要把我们的 package 塞进  getPackages()  返回的 list 里面就可以了。@Override   protected List getPackages() {     @SuppressWarnings("UnnecessaryLocalVariable")     List packages = new PackageList(this).getPackages();     // below MyAppPackage is added to the list of packages returned     packages.add(new MyAppPackage());     return packages;   }
  到这里,就已经可以写个 demo ,试一下能不能调到这个模块的方法了。记得要重新启动 RN 。 import { NativeModules } from "react-native"; const { CalendarModule } = NativeModules; ... const onPress = () => {   CalendarModule.createCalendarEvent("testName", "testLocation"); }; 更好用的原生模块
  按照上面的例子确实可以跑起来,但是你会发现有点问题,就是  CalendarModule  是没有类型检查的,而且如果每次到需要通过 NativeModules  来获取原生模块,这种方式,按照官方来说就是有点 clunky  。
  所以为了使用起来更加舒服,我们一般都会用 js 或者 ts 再包上一层,这样在其他地方使用的时候就会更加方便,而且还可以有类型检查。 /** * This exposes the native CalendarModule module as a JS module. This has a * function "createCalendarEvent" which takes the following parameters: * * 1. String name: A string representing the name of the event * 2. String location: A string representing the location of the event */ import { NativeModules } from "react-native"; const { CalendarModule } = NativeModules interface CalendarInterface {    createCalendarEvent(name: string, location: string): void; } export default CalendarModule as CalendarInterface;
  然后在其他的 RN 中使用的话就更加简单和舒服了。 import CalendarModule from "./CalendarModule"; CalendarModule.createCalendarEvent("foo", "bar"); 类型映射
  我们都知道在跨平台的时候,很多数据类型是不通用的,很多时候靠谱的就只有 字符串 了。RN 为了更方便我们 RN 和 原生 的互调,做了数据类型的映射。
  JAVA  JAVASCRIPT  Boolean ?boolean boolean boolean  Double ?number double number  String string Callback Function  ReadableMap Object ReadableArray Array
  还有几种类型也是支持的,但是未来新的  原生模块集成方式TurboModules  并不支持,所以,如果使用的是  TurboModules  ,要注意避免使用。Integer -> ?number int -> number Float -> ?number float -> number 导出常量
  原生的模块也是支持导出常量的,使用也非常简单。
  在 Module 中,重写  getConstants()  这个方法,然后再把这个在返回的 map 里面插入需要的导出的常量就可以了。@Override public Map getConstants() {    final Map constants = new HashMap<>();    constants.put("DEFAULT_EVENT_NAME", "New Event");    return constants; }
  使用的时候可以直接调用  getConstants()  来获取。const { DEFAULT_EVENT_NAME } = CalendarModule.getConstants(); console.log(DEFAULT_EVENT_NAME); 回调
  由于模块函数的调用一般都是异步的,也就无法返回参数,如果我们要返回数据,这个时候就要使用回调了。
  RN 也是支持回调的,对应的类是  com.facebook.react.bridge.Callback  。RN 支持最多两个回调函数,对应 成功回调  和 失败回调 。并且最后一个参数如果是函数,会被当做成功回调,倒数第二个参数如果是函数,就会被当成失败回调。@ReactMethod public void createCalendarEvent(String name, String location, Callback myFailureCallback, Callback mySuccessCallback) { }
  RN 中这样调用: const onPress = () => {   CalendarModule.createCalendarEventCallback(     "testName",     "testLocation",     (error) => {       console.error(`Error found! ${error}`);     },     (eventId) => {       console.log(`event id ${eventId} returned`);     }   ); };
  但其实在项目开发中,我们使用两个回调的场景也不是很多,因为很多时候跟业务之间可能会约定其他的一些状态,一般会自己定数据类型,比如会包含一个 code 或者 另一个表示状态的枚举值。然后业务再根据这个状态做对应的业务。
  官方也说到了这种类似的处理方式: @ReactMethod public void createCalendarEvent(String name, String location, Callback callBack) {   Integer eventId = ...     callBack.invoke(null, eventId); }
  然后再回调里面判断状态再处理。 const onPress = () => {   CalendarModule.createCalendarEventCallback(     "testName",     "testLocation",     (error, eventId) => {       if (error) {         console.error(`Error found! ${error}`);       }       console.log(`event id ${eventId} returned`);     }   ); };
  还有一点要注意,就是回调传过去的数据类型是要支持序列化的。另外,不能同时调用 成功回调 和 失败回调,而且成功回调 和 失败回调 只能调用一次,我感觉底层就是用了类似 Promises 一样的机制吧,一旦状态确定,就无法改变了。但是可以把 回调 储存起来,后面有结果之后再调用。 Promises
  还记得我们之前讲过的 Promises 吗?一种可以让我们以一种看似同步的代码方式来写异步的逻辑。现在 RN 也支持了。 import com.facebook.react.bridge.Promise;  @ReactMethod public void createCalendarEvent(String name, String location, Promise promise) {     try {         Integer eventId = ...         promise.resolve(eventId);     } catch(Exception e) {         promise.reject("Create Event Error", e);     } }
  RN 中接收到的就是一个 Promises 的类型了。 const onSubmit = async () => {   try {     const eventId = await CalendarModule.createCalendarEvent(       "Party",       "My House"     );     console.log(`Created a new event with id ${eventId}`);   } catch (e) {     console.error(e);   } }; 向 RN 发事件
  有些情况下,我们需要向 RN 发一些事件,比如我们的日历例子中,现在需要提醒用户现在是某个日历事项,要做什么事情。这种情况就需要原生模块向 RN 发事件,而不是等着 RN 来轮询。 RCTDeviceEventEmitter
  想要向 RN 发事件,需要一个发射器,原生代码 中使用的是  RCTDeviceEventEmitter  这个。
  那  RCTDeviceEventEmitter 这个又是从哪里来呢?
  还记得我们一开始写 Module 吗?构造方法里面有  ReactApplicationContext  ,用这个就可以了,我们可以在构造方法里面把这个保存起来,后面需要的时候再拿出来用就好了。
  需要发事件的时候,就只需要向下面这样用就好了。 WritableMap params = Arguments.createMap(); params.putString("eventProperty", "someValue");  reactContext      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)      .emit(eventName, params);
  RN 端要接收事件的话,需要注册一个监听。 componentDidMount() {    ...    const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);    this.eventListener = eventEmitter.addListener("EventReminder", (event) => {       console.log(event.eventProperty) // "someValue"    });    ...  }   componentWillUnmount() {    this.eventListener.remove(); //Removes the listener  } 其他
  RN 还支持监听  Activity  的 startActivityForResult  事件,但是我觉得这种场景应用不是很多,一般都是由原生去做对应的操作,然后再发事件给 RN,这里就不讲了。原生组件
  大概讲完了 原生模块,接下来讲一下 原生组件。我们知道 RN 提供了很多的组件给开发者使用,而且还可以导入第三方的一些组件,大部分的场景下已经能够满足我们开发的需求了。但是在某些特殊的场景或者特殊的需求,或者是一些第三方的组件不够灵活,不满足需求的,可能也需要我们开发一些原生的组件提供给 RN 使用。 ViewManager
  和 原生模块 类似的,要创建一个 原生组件 需要使用  ViewManager  来承载。ViewManager  是一个抽象类,我们一般继承其子类 SimpleViewManager  来做开发。
  官方使用了 ImageView 来做例子,我们也用这个例子来看一下吧。 public class ReactImageManager extends SimpleViewManager {    public static final String REACT_CLASS = "RCTImageView";   ReactApplicationContext mCallerContext;    public ReactImageManager(ReactApplicationContext reactContext) {     mCallerContext = reactContext;   }    @Override   public String getName() {     return REACT_CLASS;   }      @Override   public ReactImageView createViewInstance(ThemedReactContext context) {     return new ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext);   } }
  可以看到,也是有一个  getName()  的方法,用来返回组件的名称。createViewInstance
  除了  getName()  ,还有一个 createViewInstance()  的方法,这个就是实际创建组件的地方,这个方法最终会返回一个 View,最终展示的就是这个 View。public abstract class ViewManager extends BaseJavaModule{   ...   @Nonnull   protected abstract T createViewInstance(@Nonnull ThemedReactContext var1);   ... } @ReactProp
  仅仅创建出 View 还不行呀,我们还需要可以动态配置的属性。
  RN 中使用了  @ReactProp  这个注解来解析对应的属性,类似下面这样:  @ReactProp(name = "src")   public void setSrc(ReactImageView view, @Nullable ReadableArray sources) {     view.setSource(sources);   }    @ReactProp(name = "borderRadius", defaultFloat = 0f)   public void setBorderRadius(ReactImageView view, float borderRadius) {     view.setBorderRadius(borderRadius);   }    @ReactProp(name = ViewProps.RESIZE_MODE)   public void setResizeMode(ReactImageView view, @Nullable String resizeMode) {     view.setScaleType(ImageResizeMode.toScaleType(resizeMode));   }
  当 RN 中更新 属性 的时候,就会触发对应的方法。
  @ReactProp  这个注解至少需要一个 name 属性,类型是 String ,用来说明,这个属性在 RN 中对应的那个属性。
  除此之外,还可以添加一个默认值,支持  defaultBoolean , defaultInt , defaultFloat  这几种类型。如果 RN 中把某个属性删掉之后,也会触发对应的方法,并传入默认值。如果是对象类型,则会传 null 。
  @ReactProp  这个注解对被注解的方法也有要求,必须的 public void  的类型,并且第一个参数需要是 createViewInstance()  这个方法返回的类型,也就是当前 View 对象,第二个参数也只支持几种类型,boolean , int , float , double , String , Boolean , Integer , ReadableArray , ReadableMap 。注册 ViewManager
  之前我们说过,注册 Module 需要用到  ReactPackage  ,也提了一嘴,注册原生组件也会用到,这里就来了。public class MyAppPackage implements ReactPackage {     @Override    public List createViewManagers(ReactApplicationContext reactContext) {        return Arrays.asList(new ReactImageManager(reactContext));    }     @Override    public List createNativeModules(            ReactApplicationContext reactContext) {        return Collections.emptyList();    }  }
  其实如果需求里面同时需要 原生模块 和 原生组件 ,可以写在同一个 Package 里面。
  注册完之后,记得也要把 Package 注册一下,然后重启 RN ,应该就可以用了。RN 可以这样使用: const RCTImageView = requireNativeComponent("RCTImageView"); ... 
  跟 原生模块 一样,导进来直接使用是没有类型检查的,我们同样可以再包一层,加上类型限制,后面使用的时候就可以有类型检查了。 原生向 RN 发事件
  其实对于组件,不仅仅是根据参数来系那是不同的内容,有时候还需要一些交互效果,比如用户点击了这个组件,或者一个视频组件,需要通知使用方当前的播放进度。
  第一个问题是,RN 要怎么接收?
  RN 中是这么处理的,在 Manager 中重写  getExportedCustomBubblingEventTypeConstants()  返回 原生组件 发的事件名称,还有 RN 接收该事件的对属性名称。public class ReactImageManager extends SimpleViewManager {     ...     public Map getExportedCustomBubblingEventTypeConstants() {         return MapBuilder.builder().put(             "topChange",             MapBuilder.of(                 "phasedRegistrationNames",                 MapBuilder.of("bubbled", "onChange")             )         ).build();     } }
  根据例子中来讲,就是原生的组件会发一个  topChange  的事件,RN 中要接收的属性名称就是  onChange  这个。这个结构是套了几层的 map ,写的时候记得别写错了。至于里面的  phasedRegistrationNames  和  bubbled ,就是固定的写法,照着例子中这样写就好了。
  还有关键的一步,就是原生的组件要怎么把事件发给 RN?
  还记得  RCTDeviceEventEmitter  吗?这个是 Module 用来发事件 的,也跟 Module 类似,Manager 用的是 RCTEventEmitter  这个。原生组件 和 RN 通过 getId()  关联起来,也就是这个事件是发给某个特定的 View 。WritableMap event = Arguments.createMap(); event.putString("message", "MyMessage"); ReactContext reactContext = (ReactContext)getContext(); reactContext   .getJSModule(RCTEventEmitter.class)   .receiveEvent(getId(), "topChange", event);
  但是看到  receiveEvent  的时候,一开始也感到有点奇怪,Module 中使用的是 emit 。发事件嘛,用 emit  正常一点。但是官方这么写,我只能理解为 RN 接收了一条事件。
  RN 调用可以这样: class MyCustomView extends React.Component {   constructor(props) {     super(props);     this._onChange = this._onChange.bind(this);   }   _onChange(event) {     if (!this.props.onChangeMessage) {       return;     }     this.props.onChangeMessage(event.nativeEvent.message);   }   render() {     return ;   } } MyCustomView.propTypes = {   /**    * Callback that is called continuously when the user is dragging the map.    */   onChangeMessage: PropTypes.func,   ... };  const RCTMyCustomView = requireNativeComponent(`RCTMyCustomView`); RN 向 原生 发事件
  除了 原生 向 RN 发事件,还有一种情况是 RN 向 原生 发事件,这样两端就能互相通信了。比如你做了一个视频组件,RN 端想要跳转到某个时间点或者暂停、继续等情况。
  返回支持的事件
  在 Manager 中重写  getCommandsMap()  方法,在里面返回支持的事件。这是一个 Map ,可以配置多个事件。@Override public Map getCommandsMap() {     return MapBuilder.of("play", COMMAND_PLAY);   }
  处理事件
  在 Manager 中重写  receiveCommand()  方法,在这里面处理事件。@Override   public void receiveCommand(     @NonNull FrameLayout root,     String commandId,     @Nullable ReadableArray args   ) {     super.receiveCommand(root, commandId, args);     switch (commandIdInt) {       case COMMAND_PLAY:         // 处理事件         doSomething(root);         break;       default: {}     }   }
  RN 端调用
  原生端这样就搞完了,RN 端要怎么调用呢?
  第一步,要获取对应的 ViewId,所以就需要使用 ref 来获取对应的组件对象的引用,然后再通过  findNodeHandle(ref)  来获取到 ViewId。
  第二步,通过  UIManager.dispatchViewManagerCommand()  来发送对应的事件。import React, { useEffect, useRef } from "react"; import { UIManager, findNodeHandle } from "react-native";  import { MyViewManager } from "./my-view-manager";  // 调用这个方法就可以向 原生组件 发事件 const doSomething = (viewId) =>   UIManager.dispatchViewManagerCommand(     viewId,     UIManager.MyViewManager.Commands.play.toString(),     // 这里可以传参数     []   );  export const MyView = () => {   const ref = useRef(null);    useEffect(() => {     // 获取 viewId     const viewId = findNodeHandle(ref.current);   }, []);      return (        ); };
  在官方文档的最后,写了一个例子,介绍如何在 RN 中嵌入 Fragment ,但是我感觉这种场景很少用到,这里就不细说了,感兴趣的同学可以去看看官方文档。

倾听你所想听Earfree无线蓝牙耳机测评前言自从3。5mm耳机孔被众多手机厂商取消以来,TWS真无线蓝牙耳机已经成为了每个用户的必需品,近期弱水科技推出了新品主动降噪蓝牙耳机Earfree无线蓝牙耳机,它具有六大优势,最首家ALIENWARE红店空降北京三里屯太古里挑战边界8月30日,首家ALIENWARE红店在北京三里屯太古里盛大开业。这是继ALIENWARE在苏州成都太古里北京国贸三家旗舰店之后,于前沿潮流时尚中心北京三里屯开设的又一家集产品服务社交取经后的Supercell当社交的目标被聚焦后,留住用户的是什么?推广费用水涨船高的年代,Supercell新游发布立刻获得了媒体的争相报道,这就是已经塑造的品牌力量。不过受益者并非只有Supercell自监管层首次公开表态高比例抽成严重影响产业的可持续发展如今看来,平台下调分成已箭在弦上。7月29日,中国国际数字娱乐产业大会(CDEC)在上海浦东嘉里酒店召开,全国政协委员中国音像与数字出版协会理事长孙寿山发表主旨演讲。在演讲当中,孙洋葱工厂布朗尼LED补光灯上手前言都说摄影是用光钱的艺术。哦,不对。摄影是用光的艺术。今儿,特特就带大家来看看我最近入手的洋葱工厂布朗尼LED补光灯,并附上一张使用它拍摄产品图,很多时候器材不重要,重要的是想法带上心想柳橙机随时喝一杯纯正的橙汁从吃饱到吃出营养,我们的生活发生了翻天覆地的变化,尤其2020年这个不平凡的年份,因为新冠病毒让人们拼起了免疫力。为了增强免疫力人们加强了运动,改变了生活习惯,注重营养均衡,懂得如宝妈的晨起生活先从牛排开始万事都是双刃剑,一点都不假,有俩娃的日子是辛苦的也是快乐的。生完老大8年后赶上国家二胎政策,首当其冲生了二宝。时光荏苒,不知不觉二宝也四岁了。为了助力两娃健康成长,我一个事业型的知从单向输出到双向深度互动虎牙用技术驱动直播变革直播的形态正在悄然发生变化。发展了近15年,伴随着移动互联网带来的人口红利达到边界,网络直播行业正在面临新一轮的挑战,用户对直播内容质量互动体验等要求变得越来越高。反映到直播平台的孙悟空黑猫警长各显神通,和平精英和上美影整了一出好活美猴王的金箍棒与黑猫警长的飞天摩托车孰强?9月8日,和平精英光影冒险版本正式上线。在新游戏版本中,和平精英与上美影展开了深度联动,四大经典动画IP大闹天宫宝莲灯黑猫警长九色鹿被深度漫威IP加持,网易的竞技梦这次能成么?多元化的方向和跨圈纳新的可能CCG融合自走棋思路的漫威对决国服上线了,上线首日表现不俗,不仅登顶了TapTap热门榜,并且评分还稳定在了9。0分,从侧面反映出核心卡牌圈对游戏的认可揭开重生边缘的面纱一次自我成长的探索尝试迎难而上才能在未来更进一步8月28日,NExTStudios第一次进行了重生边缘的完整版的测试,结果有好有坏。既有玩家对于包括芯控在内等创新玩法的认可,也有对游戏优化的吐槽。对于不
弄清楚来龙去脉选电脑3显示器选择为什么不选好显卡再选显示器?这是有原因的,同样34寸的显示器,一个是4k显示,一个是2k显示,显示器的频率一个75hz,一个144hz,那显卡选择起来天差地别。我做图和编又一国产手机量产芯片突破,三芯合并,秒充超越苹果华为众所周知,国产高端芯片正处于卡脖子的关键阶段,华为为此受到了巨大的影响,不仅是麒麟Soc,就连5G射频充电等方面都受到了不同程度的影响。对于这一现状,各大国内手机厂商也都加大芯片领这是一款被严重低估的华为手机,一千多元搭载麒麟顶级芯片说起华为,大家第一点想到的肯定就是芯片问题,自从芯片受限以后就是一代不如一代,尤其是P50系列阉割了5G版本以后,竞争力就减弱了一大截。回顾过去几年华为推出的几款手机,华为nova罗永浩因为要烧投资人的钱,所以没勇气再做手机了Tech星球4月17日消息,4月16日,有网友在社交平台问罗永浩还有没有勇气再做一款手机,对此,罗永浩回应称因为要烧投资人的钱,所以我确实没这勇气了。罗永浩表示,如果不考虑财务回报9个实用的手机App,满足你的各种需求你的手机上都有哪些好用的软件呢?今天就给大家分享9个冷门逆天的硬核App,满足你的各种需求,真是后悔没早点知道。01简单搜索当我们在网上查找问题的时候,总是会遇到很多广告无关的内容极客简报WWDC或发布收官之作马斯克收购推特意图曝光游戏版号发放老板喜极而泣没有手机的魅族发布会今年神舟十四十五号将发射WWDC或发布M1Mac收官之作在上次春季发布会最后,苹果宣布新款MacPro将很快登场,目前来看,6月份的WW大号版的苹果13?大家好,我是小温,今天为大家带来一款平板号称大号苹果13价格确是便宜很多的那种全新机,这款机子就是iPadmini6。iPadmini6屏幕采用的是8。3英寸看短视频和电视也是非常余承东果然没有吹牛!华为Mate50如期而至,三大亮点依旧是旗舰机喜欢华为手机的朋友肯定也发现了,自从发布华为P50系列之后,华为已经有一段时间没有新机上市了。不过根据知情人的爆料,华为MateX3折叠屏手机已经在路上,同时华为Mate50系列有周小川第三方机构想做数字货币或参与支付系统,就不能耍小聪明来源国是直通车微博原标题周小川第三方机构想做数字货币或参与支付系统,就不能耍小聪明中国金融学会会长,中国人民银行原行长周小川今天在出席2022清华五道口全球金融论坛时表示,第三方机Makerdao坚持Defi协议应该利用世界的资产来扩展美国财政部官员我们认为加密货币不会被大规模用于逃避制裁美国财政部认为加密货币不能被大规模用于逃避制裁。一位财政部高级官员指出它作为非法金融媒介的份额并不像使用现金那么大。财政部对使光峰科技取得IATF16949汽车行业质量管理体系认证光峰科技取得IATF16949汽车行业质量管理体系认证财联社4月17日电,光峰科技公告,公司近日取得IATF169492016质量管理体系认证证书。通过该体系的认证表明公司在车载激