(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

RxJava使用场景

文章目录

  • RxJava使用场景
    • 1.为什么学习RxJava?
      • 1.1什么是ReactiveX?
      • 1.2什么是RxJava?
      • 1.3RxJava思维
      • 1.4生活中的例子
      • 1.5程序中的例子
      • 1.6RxJava架构
      • 1.7RxJava基础学习资料
    • 2.RxJava应用场景
      • 2.1核心思想
      • 2.1.1图片下载案例
        • 2.1.1.1传统思维方式
        • 2.1.1.2RxJava思维方式
      • 2.2RxJava配合Retrofit
        • 2.2.1案例
      • 2.3防抖
      • 2.4网络嵌套
        • 2.4.1 flatMap操作符思想
      • 2.5doOnNext运用
        • 2.5.1案例
    • 3.打赏鼓励
      • 3.1微信打赏
      • 3.2支付宝打赏

1.为什么学习RxJava?

(1)改变思维来提升效率
(2)Rx提供了一系列的操作符,你可以使用它们来过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable,这些操作符让执行和复合变得非常高效。

1.1什么是ReactiveX?

(1)ReactiveX是Reactive Extensions的缩写,一般简写为Rx,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流。

(2)微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理。

(3)Rx可以这样定义:Rx = Observables + LINQ + Schedulers。

(4)ReactiveX.io给的定义是,Rx是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华。

1.2什么是RxJava?

(1)在RxJava中,一个实现了Observer接口的对象可以订阅(subscribe)一个Observable类的实例。

(2)订阅者(subscriber)对Observable发射(emit)的任何数据或数据序列作出响应。

(3)这种模式简化了并发操作,因为它不需要阻塞等待Observable发射数据,而是创建了一个处于待命状态的观察者哨兵,哨兵在未来某个时刻响应Observable的通知。

1.3RxJava思维

响应式编程

1.4生活中的例子

(1)起点(分发事件(PATH):我饿了)
(2)下楼
(3)去餐厅
(4)点餐
(5)终点(吃饭 消费事件)

1.5程序中的例子

(1)起点(分发事件:点击登录)
(2)登录API
(3)请求服务器
(4)获取响应码
(5)终点(更新UI登录成功 消费事件)

  • 从起点到终点事件没有断掉,每一个事件依赖于上一事件的完成,环环相扣。

1.6RxJava架构

(1)github:https://github.com/ReactiveX/RxJava
(2)Author:JakeWharton(Android之神)
(3)Rx系统架构官网
http://reactivex.io

1.7RxJava基础学习资料

2.RxJava应用场景

2.1核心思想

从事件起点到终点,每一个事件都紧密依赖于上一事件的完成,环环相扣,没有中断。

2.1.1图片下载案例

2.1.1.1传统思维方式

(1)无法固定每个程序员的思维(会导致接手项目的程序员无法看懂),即每个程序员都有一套自己实现的思维。

  • A程序员:35356453 自己的思维 不同 封装方法…
  • B程序员:46576576 自己的思维 不同 全部写在一起
  • C程序员:43643654 自己的思维 不同 new Thread
  • D程序员:66545655 自己的思维 不同 使用 线程池

(2)代码

public class DownLoadActivity extends AppCompatActivity {private static final String         TAG  = "DownLoadActivity";/*** 1.网络图片的链接地址*/private final static String         PATH = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2F01.minipic.eastday.com%2F20161208%2F20161208151453_9440fdc7642c62ef1c4cb67425b606d0_9.jpeg&refer=http%3A%2F%2F01.minipic.eastday.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620538239&t=64eb953a8e19440231bd0527542de045";private              ProgressDialog progressDialog;@InjectView(R.id.iv_img)private ImageView iv_img;@InjectView(R.id.btn_download_image_action)private Button btn_download_image_action;@InjectView(R.id.btn_rx_java_download_image_action)private Button btn_rx_java_download_image_action;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_down_load); InjectUtils.injectView(this);InjectUtils.injectViewAndEvent(this);}@OnClick({ R.id.btn_download_image_action, R.id.btn_rx_java_download_image_action })public void click(View view) {if (view == btn_download_image_action) {downloadImageAction();}}private final Handler handler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(@NonNull Message msg) {Bitmap bitmap = (Bitmap) msg.obj;iv_img.setImageBitmap(bitmap);if (progressDialog != null) {progressDialog.dismiss();}return false;}});public void downloadImageAction() {progressDialog = new ProgressDialog(this);progressDialog.setTitle("下载图片中..."); progressDialog.show();new Thread(new Runnable() {@Overridepublic void run() {try {URL url = new URL(PATH);HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();httpURLConnection.setConnectTimeout(5000);int responseCode = httpURLConnection.getResponseCode(); // 才开始 requestif (responseCode == HttpURLConnection.HTTP_OK) {InputStream inputStream = httpURLConnection.getInputStream();Bitmap bitmap = BitmapFactory.decodeStream(inputStream);Message message = handler.obtainMessage();message.obj = bitmap; handler.sendMessage(message);}} catch (Exception e) {e.printStackTrace();}}}).start();}}

2.1.1.2RxJava思维方式

(1)角色:起点与终点

  • 起点是被观察者Observable
  • 终点代表观察者Observer

(2)为什么插入了观察者设计模式?
因为被观察者发生了改变,观察者就会同样作出相应改变。

(3)案例

    /*** RxJava思维*/public void rxJavaDownloadImageAction() {/*** TODO 2.第二步内部分发PATH,*/Observable.just(PATH)/*** TODO 3.第三步* 1.下载图片事件*/.map(new DownloadImageFunction())/*** 2.为图片添加水印事件*/.map(new AddWaterMarkFunction())/*** 3.添加下载日志记录事件*/.map(new AddDownloadLogRecordFunction())/*** 4.为上下游事件线程分配执行线程,以上事件操作在io线程中执行,以下* 操作在Android主线程中执行,详见UpDownObservableTransformer设置*/.compose(new UpDownObservableTransformer<>())/*** 5.订阅 将起点和终点订阅起来*/.subscribe(new DownloadImgObserver<>());}/*** 1.下载图片功能*/class DownloadImageFunction implements Function<String, Bitmap>{@Overridepublic Bitmap apply(String s) throws Exception {URL url = new URL(PATH);HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();httpURLConnection.setConnectTimeout(5000);int responseCode = httpURLConnection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {InputStream inputStream = httpURLConnection.getInputStream();Bitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;}return null;}}/*** 2.为图片添加水印功能*/class AddWaterMarkFunction implements Function<Bitmap,Bitmap>{@Overridepublic Bitmap apply(Bitmap bitmap) throws Exception {Paint paint = new Paint();paint.setTextSize(20);paint.setColor(Color.RED);return BitmapUtil.drawTextToBitmap(bitmap, "这是图片水印文字",paint, 88 , 88);}}/*** 3.添加下载图片日志功能*/class AddDownloadLogRecordFunction implements Function<Bitmap,Bitmap>{@Overridepublic Bitmap apply(Bitmap bitmap) throws Exception {Log.d(TAG, "apply: 下载图片日志" + System.currentTimeMillis());return bitmap;}}/*** 5.终点(观察者)* 5.1对上游事件的观察者* 5.2上游事件指的是下载图片功能、为图片添加水印功能、添加下载图片日志功能* 5.3订阅了上游事件之后,首先会进入onSubscribe()开始订阅此为第1步* 5.4just操作符分配图片加载路径事件为第2步* 5.5开始执行下载图片功能事件及其后绪事件为第3步* 5.6当由io线程切换到主线程之后,进入onNext()执行为第4步* 5.7当所有事件执行完成,则进入onComplete()执行为第5步* @param <Bitmap>*/class DownloadImgObserver<Bitmap> implements Observer<Bitmap>{/*** 订阅开始* 预备 开始 要分发* TODO 1.第一步*/@Overridepublic void onSubscribe(Disposable d) {progressDialog = new ProgressDialog(DownLoadActivity.this);progressDialog.setTitle("download run");progressDialog.show();}/*** TODO 4.第四步* 拿到事件* @param bitmap*/@Overridepublic void onNext(Bitmap bitmap) {iv_img.setImageBitmap((android.graphics.Bitmap) bitmap);}@Overridepublic void onError(Throwable e) {}/*** TODO 5.第五步* 完成事件*/@Overridepublic void onComplete() {if (null!= progressDialog){progressDialog.dismiss();}}}
public class BitmapUtil {/*** 图片上绘制文字 加水印* @param bitmap* @param text* @param paint* @param paddingLeft* @param paddingTop* @return*/public static final Bitmap drawTextToBitmap(Bitmap bitmap, String text,Paint paint, int paddingLeft, int paddingTop) {Bitmap.Config bitmapConfig = bitmap.getConfig();paint.setDither(true); //1.获取跟清晰的图像采样paint.setFilterBitmap(true);if (bitmapConfig == null) {bitmapConfig = Bitmap.Config.ARGB_8888;}bitmap = bitmap.copy(bitmapConfig, true);Canvas canvas = new Canvas(bitmap);canvas.drawText(text, paddingLeft, paddingTop, paint);return bitmap;}
}

(4)数据由起点流向终点的过程中,上一级事件的数据类型决定了下一级事件的初始类型

  • 起点PATH是个String类型的数据,它的下一级事件为下载图片事件
  • 下载图片事件的初始数据类型即为String,而下载图片事件执行之后数据变换为Bitmap类型
  • 即决定了为图片添加水印事件的初始类型为Bitmap.
  • 当在上一级事件中将数据类型做出变更,其流转到下一事件时,下一事件的初始数据类型即为上一事件变更后的数据类型。

(5)在上一级事件流向下一级事件的过程中,可以指定上一级事件(功能)在什么线程中执行。

  • compose()中指定
  • 例如:可指定上一级事件在io线程中执行,而下一级事件在主线程中执行。
/*** 为上下游事件线程分配执行线程* 1.2指定上游事件在io线程中执行* 1.3指定下游事件在主线程中完成* 1.4ObservableTransformer<Upstream, Downstream>泛型接口* (1)Upstream:the upstream value type,上游数据类型* (2)Downstream:the downstream value type,下游数据类型*/
public class UpDownObservableTransformer<UD> implements ObservableTransformer<UD, UD> {@Overridepublic ObservableSource<UD> apply(Observable<UD> upstream) {return upstream.subscribeOn(Schedulers.io())//1.指定上游事件在io线程中执行.observeOn(AndroidSchedulers.mainThread())//2.指定下游事件在主线程中完成.map(new OtherFunction<>());//3.指定其他的下游事件}/*** 可以通过map操作符插入其他下游事件* @param <UD>*/class OtherFunction<UD> implements Function<UD,UD> {private static final String         TAG  = "UDFunction";@Overridepublic UD apply(UD ud) throws Exception {Log.d(TAG, "apply:新的下游事件");return ud;}}
}

2.2RxJava配合Retrofit

(1)主流框架都是Retrofit+OkHttp+RxJava
(2)Retrofit请求服务器通过OkHttp拿到响应数据之后给到RxJava,RxJava处理响应数据。
(3)请求是通过OkHttp,Retrofit只是一个管理者,它控制着OkHttp去请求网络,响应的结果丢给RxJava来处理。

2.2.1案例

(1)先获取总数据
(2)然后根据总数据API获取Item数据
(3)即需要写两个接口去完成整个功能

public interface WangAndroidApi {/*** 1.异步线程 耗时操作* 1.1总数据* 1.2RxJava事件起点* @return*/@GET("project/tree/json")Observable<ProjectBean> getProject();/*** ITem数据* @param pageIndex* @param cid ?cid=294* @return*/@GET("project/list/{pageIndex}/json")Observable<ProjectItem> getProjectItem(@Path("pageIndex") int pageIndex, @Query("cid") int cid);  // 异步线程 耗时操作
}

2.3防抖

(1)一个功能疯狂的点击,几秒之内点击了20以上,要控制它只响应1次,这即为防抖。
(2)使用rxbinding2库防止控件抖动

        //1.对bt_anti_shake控件进行防抖处理RxView.clicks(bt_anti_shake)//2.设置间隔2秒钟响应一次.throttleFirst(2000, TimeUnit.MILLISECONDS).subscribe(new MyConsumer<Object>());

2.4网络嵌套

(1)先查主数据,然后再根据主数据查询item数据,即为网络嵌套。
(2)因嵌套层级过多引起的代码可读性差的问题

   /*** 1.防抖功能 + 网络嵌套(这种是负面教程,嵌套的太厉害了)* 1.1嵌套层数太多,代码可阅读性太差*/private void antiShakeActon() {//1.对bt_anti_shake控件进行防抖处理RxView.clicks(bt_anti_shake)//2.设置间隔2秒钟响应一次.throttleFirst(2000, TimeUnit.MILLISECONDS).subscribe(new MyConsumer<Object>());}/*** 1.先查询主数据,再根据主数据查item数据* 2.自定义泛型类实现Consumer<T>泛型接口* @param <T>*/class MyConsumer<T> implements Consumer<T>{@Overridepublic void accept(T t) throws Exception {//1.先查询主数据api.getProject()./*** 1.为上游事件与下游事件分配执行线程* 1.1此案例上游事件在io线程中执行* 1.2下游事件在主线程中执行*/compose(new UpDownObservableTransformer())/*** 2.设置下游事件订阅者*/.subscribe(new QueryConsumer());}}/*** 1.主数据查询事件* 2.自定义泛型类实现Consumer<T>泛型接品* 2.1此例中已经明确指定了Consumer<T>泛型接口中的T为ProjectBean,因此不再需要在类的声明* 中限定泛型类型* 2.2如果一个类继承自一个泛型类,继承的泛型类中已经明确的说明了泛型中存放的是什么类型,* 那么在声明当前类时,可以省略类名后面的<>。*/class QueryConsumer implements Consumer<ProjectBean>{@Overridepublic void accept(ProjectBean projectBean) throws Exception {for(DataBean dataBean : projectBean.getData()){//1.根据主数据编号查询item数据api.getProjectItem(1, dataBean.getId())/*** 1.为上游事件与下游事件分配执行线程* 1.1此案例上游事件在io线程中执行* 1.2下游事件在主线程中执行*/.compose(new UpDownObservableTransformer())/*** 2.设置下游事件订阅者*/.subscribe(new QueryProjectItemConsumer());}}}/*** 1.item数据查询事件*/class QueryProjectItemConsumer implements Consumer<ProjectItem>{@Overridepublic void accept(ProjectItem projectItem) throws Exception {//可以做UI显示相关操作Log.d(TAG, "accept: " + projectItem);}}

(3)使用flatMap操作符网络嵌套过多代码可读性差的问题

/*** 1.使用rxbinding2库防止控件抖动* 2.使用flatMap操作符网络请求嵌套过多的问题*/private void antiShakeActonUpdate() {RxView.clicks(bt_anti_shake)//1.设置控件间隔2秒钟响应一次.throttleFirst(2000, TimeUnit.MILLISECONDS)//2.指定下游事件在io异步线程中执行.observeOn(Schedulers.io()).flatMap(//3.插入请求主数据事件new Function<Object, ObservableSource<ProjectBean>>() {@Overridepublic ObservableSource<ProjectBean> apply(Object o) throws Exception {return api.getProject();}}).flatMap(new Function<ProjectBean,ObservableSource<DataBean>>(){//4.插入遍历事件@Overridepublic ObservableSource<DataBean> apply(ProjectBean projectBean) throws Exception {return Observable.fromIterable(projectBean.getData());}}).flatMap(new Function<DataBean,ObservableSource<ProjectItem>>(){//5.插入获取item数据事件@Overridepublic ObservableSource<ProjectItem> apply(DataBean dataBean) throws Exception {return api.getProjectItem(1,dataBean.getId());}})//6.切换回UI线程.observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<ProjectItem>() {@Overridepublic void accept(ProjectItem projectItem) throws Exception {//执行相关UI操作Log.d(TAG, "accept: " + projectItem);}});}

2.4.1 flatMap操作符思想

起点可以分发一个数据
onNext(1);
|
|
|
flatMap 自己分发 10个数据 给下面
1 --> 多发送 10次 1+“DDD”
|
|
|
subscribe{
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
1+“DDD”
}


(1)起点分发一个数据
(2)flatMap可以往下游事件中分发10个数据。
(3)之所以可以发送多条数据,是由flatMap()方法中接受的参数数据类型ObservableSource<?>决定的。
(4)防抖功能运行在主线程,flatMap操作最好放在异步线程,不然会发生崩溃。
(5)自己创建发射器发多次
.flatMap(new Function<ProjectBean,ObservableSource<DataBean>>(){//4.插入遍历事件@Overridepublic ObservableSource<DataBean> apply(ProjectBean projectBean) throws Exception {//自己创建发射器发多次return Observable.fromIterable(projectBean.getData());}
})

2.5doOnNext运用

(1)先注册
(2)然后切换到UI线程
(3)UI线程登录又切换到子线程
(4)然后再切换到UI线程
(5)即频繁的在主线程与子线程做UI切换的操作
(6)这种业务需求就可以使用doOnNext()完成

2.5.1案例

public void request2() {MyRetrofit.createRetrofit().create(IReqeustNetwor.class)//@TODO 第2步// 1.请求服务器注册操作.registerAction(new RegisterRequest())//2.指定上游事件在io异步线程中执行.subscribeOn(Schedulers.io())//3.第定下游事件在主线程中执行.observeOn(AndroidSchedulers.mainThread())//@TODO 第3步//4.注册完更新UI.doOnNext(new Consumer<RegisterResponse>() {@Overridepublic void accept(RegisterResponse registerResponse) throws Exception {//注册完成之后,更新注册UI}})//5.指定下游事件在异步线程中执行.observeOn(Schedulers.io())//@TODO 第4步//6.登录事件.flatMap(new Function<RegisterResponse, ObservableSource<LoginResponse>>() { // todo 4@Overridepublic ObservableSource<LoginResponse> apply(RegisterResponse registerResponse) throws Exception {Observable<LoginResponse> loginResponseObservable = MyRetrofit.createRetrofit().create(IReqeustNetwor.class).loginAction(new LoginReqeust());return loginResponseObservable;}})//7.指定下游事件在主线程中执行.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<LoginResponse>() {/*** 一定是主线程,为什么,因为 subscribe 马上调用onSubscribe* @param d*/@Overridepublic void onSubscribe(Disposable d) {//1.第1步progressDialog = new ProgressDialog(RequestActivity.this);progressDialog.show();disposable = d;}@Overridepublic void onNext(LoginResponse loginResponse) {//@TODO 第5步//登录完成之后,更新登录的UI}@Overridepublic void onError(Throwable e) {}/*** @TODO 第6步*/@Overridepublic void onComplete() {if (progressDialog != null) {progressDialog.dismiss();}}});}

(1)Disposable 用了之后要消毁,不然会引发内存泄漏。
(2)是因为事件在由上而下分发执行过程中,每次分发都会判断Disposable是否被释放,isDisposed,如果没有中断则继续执行,如果中断了就不执行。
(3)中断的原因,有些时候Activity会被用户给中断掉。

3.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

3.1微信打赏

3.2支付宝打赏

【27】RxJava使用场景相关推荐

  1. java半球最多_多是东半球最全的RxJava使用场景小结

    1.Scheduler线程切换html 这样的场景经常会在"后台线程取数据,主线程展现"的模式中看见java Observable.just(1, 2, 3, 4) .subscr ...

  2. 0基础学习VR全景平台篇第27章:场景管理-视角功能

    大家好,欢迎收看蛙色平台免费教程! 功能位置示意 一.本功能将用在哪里? 视角功能:指观看者打开场景时,默认展示的位置内容,可针对视角显示范围.视角远近范围进行设置. 应用场景:几乎每个作品的具体场景 ...

  3. 可能是东半球最全的RxJava使用场景小结

    http://blog.csdn.net/theone10211024/article/details/50435325

  4. 三维场景图:用于统一语义、三维空间和相机的结构

    三维场景图:用于统一语义.三维空间和相机的结构 3D Scene Graph: A structure for unified semantics, 3D space, and camera 论文链接: ...

  5. RxJava学习资源

    RxJava resources Blog 给 Android 开发者的 RxJava 详解 -强烈推荐 扔物线的文章 讲解非常详细 NotRxJava懒人专用指南 -这篇入门极力推荐,手把手,深入浅 ...

  6. Unity3D研究院之异步加载游戏场景与异步加载游戏资源进度条(三十一)

    异步任务相信大家应该不会陌生,那么本章内容MOMO将带领大家学习Unity中的一些异步任务.在同步加载游戏场景的时候通常会使用方法 Application.LoadLevel("yourSc ...

  7. Android开发---RxJava+Retrofit封装

    本文内容是基于Retrofit + RxJava做的一些巧妙的封装.参考了很多文章加入了一些自己的理解,请多指教.源码地址https://github.com/Hemumu/RxSample 先放出b ...

  8. 关于RxJava防抖操作

    关于RxJava防抖操作 在实际开发中为了防止用户手抖点开两个重复的界面,我们会做防抖处理.(这里吐槽一下微信,快速点击朋友圈就可以点开多个页面...)解决的老办法我就不介绍了,这里我们主要说说利用R ...

  9. 【计算机视觉】有限标签的场景图预测

    文献题目:Scene Graph Prediction with Limited Labels 摘要 诸如视觉基因组之类的视觉知识库为计算机视觉中的众多应用提供了支持,包括视觉问答和字幕,但存在稀疏. ...

最新文章

  1. 指尖大冒险、跳一跳升级版html5游戏全代码
  2. centos mysql数据迁移_Mysql 5.7.17 离线版安装和数据迁移(centos 7)
  3. 使用 EthPM 包管理工具
  4. 【转】linux shell 中21含义
  5. php设计一个盒子类代码_PHP设计模式之简单工厂模式(Simple Factory)代码实例大全(七)...
  6. 数据结构和算法———P1 绪论
  7. java进程cpu使用率高_什么会导致Java应用程序的CPU使用率飙升?
  8. 图像标注工具labelImg使用方法
  9. wireshark+rtmp协议分析
  10. 全球国家或地区 及其 区号
  11. 简述autocad在测绘工程中的应用_AutoCAD在工程测绘制图中的应用
  12. windows开启nfs_win7专业版怎么开启nfs_win7专业版启用nfs步骤
  13. WIN7去掉快捷方式小箭头
  14. 海贼王热血航线正在连接服务器,海贼王热血航线为什么连接不了服务器?老是说人已满进不去?...
  15. 自动驾驶之-MATLAB环境下基于深度学习的语义分割
  16. 【历史上的今天】4 月 10 日:Github 诞生;人类第一张黑洞照片;计算机延误航天飞机
  17. 【ECCV2018 UPDT】Unveiling the Power of Deep Tracking[特征融合]
  18. 云音乐vue开发日记
  19. AdGuard推荐设置
  20. 实用的一些网站 合集

热门文章

  1. 【nowcoder】笔试强训Day9
  2. android动画实例
  3. 什么是大数据?大数据能做什么?
  4. 推动营销模式创新,华为云大数据解决方案加码企业数字化转型
  5. 使用python+selenium对12306车票数据读取
  6. table表格模板(自用)
  7. Vitalik:为何需要区块链投票?
  8. 【LTE】LTE轻松进阶学习笔记-接口协议(4)
  9. 仿QQ聊天软件(登录界面、好友界面、聊天界面)-Java(Swing、Socket)
  10. MATLAB代码:电动汽车有序充电策略 基于峰谷分时电价引导下的电动汽车充电负荷优化