Coder Social home page Coder Social logo

technotes's People

Contributors

vvlavida avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

technotes's Issues

RxJava on Android

The introduction to Reactive Programming you've been missing

RxJava 是 ReactiveX 的一部分,一组开源库。它们有许多不同的库,包括 JavaScript, Groovy, Ruby, Java, C#,以及其他。然而,它们都有着同样的概念,这就是 functional 编程。

ReactiveXReactive Extensions的缩写,一般简写为Rx。
ReactiveX 是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华

为什么用RxJava

我们都知道移动开发是困难的。移动用户期望即时响应,而且还有在不同的线程间来回切换的需求。除了主线程,你还要做网络连接,同时你还需要在后台处理其他的各种不同的事情。最重要的是,你不能阻塞 UI 线程。

RxJava 是解决这类问题的好方法,因为他能够使得线程间的切换比较容易。这已经集成在框架里面了。异步操作非常笨重而且容易出错,RxJava 使得你不用再这样做了,这也是你能把不同的线程组合在一起的原因。

我觉得 imperative 编程是我们不应该采用的方法。当然,面向对象编程已经流行很多年了。它已经深入到了现代程序员的骨髓里了。每个人都盲目的使用它,但是它不是我们开发软件的必需品

Functional 编程是 RxJava 里面的概念,而且我觉得用这种方法,代码更加健壮,而且永远不需要维护状态了。代码更加可靠而且你知道它一定工作。

Retrolambda

写在前面

  • Retrolambda 是 Java 6/7 对 Lambda 表达式的非官方兼容方案,它的向后兼容性和稳定性是无法保障的,因此对于企业项目,使用 Retrolambda 是有风险的。
  • Lambda 是把双刃剑,它让你的代码简洁的同时,降低了代码的可读性。

事件总线(EventBus)分析

文档: http://greenrobot.org/eventbus/documentation/

在安卓中处理不同组件之间的事件传递依靠广播机制,即Intent/BroadcastReceiver机制,其原理类似于传感网中的Ad hoc网络模式,所有组件处在一种无序状态;

事件总线机制则引入中心控制节点来集中管理事件,类似于移动通信网络中的基站功能。

总线这个概念来自于计算机,计算机中各种功能部件如CPU,显卡之类不会采用两两互联的方式,那样布线会非常复杂,实际是使用总线作为公共通信干线,挂载上所有的功能部件。

事件总线框架采用订阅/发布模型

在这个模型中包含以下元素

1.事件类,这是要传递的事件对象。
2.事件总线,是中心控制节点,负责管理事件的注册,接收发布的事件,并完成事件匹配以进行事件处理。
3.发布者,负责分发事件。
4.订阅者,负责事件处理并注册到事件总线。

事件总线模型比广播机制的优势在于

1.简化了组件之间的通信
2.实现了事件分发和事件处理的解耦,因此二者可以在不同线程中实现。
3.扩展了事件类,实际上事件类就是根类Object,而不必藏身在Intent中了。

事件总线模型不能完全替代广播机制,因为广播机制可以完成跨App间组件调用。

Android进程守护

洗洗睡吧。
如果实在要做,建议引导用户添加白名单。

设备未ROOT情况下,大致的解决方案如下:

  • Service设置成START_STICKY,kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

当系统内存非常紧张并且轮到 Service 进程被杀的时候,这时候在非 root 的 Android 手机/平板 都是无力回天的。一般来说系统杀掉 Service,过 5 - 10 秒会再次启动 Service(如果有应急机制)。

其实问题的实质就是:系统重启Service 后,如何保持与重启前一样?

设置 onStartCommand() 的返回值(这里牵扯到 Service 的启动方式)。onStartCommand() 有其中两个返回值:
START_STICKY:kill 后会被重启,但重启后调用 onStartCommand(Intent,int,int),但是传进来的 Intent这个参数为 null;
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

  • ​通过 startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别​,除非在系统内存非常缺,否则此进程不会被 kill

是的,用户能看见你。

  • 双进程Service:守护进程和主进程之间相互监视,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

清理工具清理后无效。

  • QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死

仅能保护自己不被清理工具清理后台时杀死。

  • Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android-Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在:
  1. 用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。

  2. 在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。

  3. 主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。

    开源方案:NativeSubprocess
    注意: Android 5.0上采用fork的方式是无法起作用的,当父进程被杀死的时候,对应fork出来的子进程会被系统主动调用waitpid将其停止并回收.在fork进程这个调用上,iOS也可以调用fork,但是只要你设备没有越狱,fork是直接返回错误的。

  • 联系厂商,加入白名单

如何提高Android代码的可测试性?

使用MVP架构,对视图逻辑(view层)和业务逻辑(presenter层)进行拆分,就可以对UI、业务代码分别进行测试。UI测试引入Espresso,业务层单元测试引入junit,生成测试mock对象引入mockito,为了支撑mockito引入dexmaker,hamcrest的引入使得测试代码的匹配更接近自然语言,可读性更高,更加灵活。

XCoder from 0 to 1

记录个人iOS平台学习路径

整体思路:

  • 1.了解iOS平台历史、现状及发展方向
  • 2. 了解iOS技术生态,熟悉相关概念
  • 3. 快速实践,了解开发环境
  • 4. 学习Objective-C
  • 5. 实践
  • 6. 开源项目学习

GitBook 《iOS要点摘录》

如何提高Android代码的可测试性?

使用MVP架构,对视图逻辑(view层)和业务逻辑(presenter层)进行拆分,就可以对UI、业务代码分别进行测试。UI测试引入Espresso,业务层单元测试引入junit,生成测试mock对象引入mockito,为了支撑mockito引入dexmaker,hamcrest的引入使得测试代码的匹配更接近自然语言,可读性更高,更加灵活。

Android Webview URL资源加载拦截

定制user-scheme(如zl://xxxxx/1234),实现html页面加载离线资源。
如: 页面使用标签的 src = zl://resourceid/xxxx 访问离线资源file:///android_asset/drawable/test.png"

SubWebViewClient.java

// 这个回调可以通知主程序WebView处理的资源(css,js,image等)请求,并允许主程序进行处理后返回数据。
// 如果主程序返回的数据为null,WebView会自行请求网络加载资源,否则使用主程序提供的数据。
//(非UI线程)
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@OverRide
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return null;
}
return WebResourceSchemeController.handle(super.shouldInterceptRequest(view, request), request.getUrl().toString());
}

具体处理:

@OverRide
public WebResourceResponse webResourceIntercept() {
try {
InputStream localCopy = context.getAssets().open("drawable/test.png");
// 页面使用标签的 src = zl://resourceid/xxxx 访问离线资源file:///android_asset/drawable/test.png"
// url映射到本地路径的页面,在替换scheme之外,还需去掉url所带的参数
response = new WebResourceResponse("image/png", "UTF-8", localCopy);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}

iOS UIWebView URL拦截

在做app开发时,通常会因为页面的javascript文件比较大导致加载速度很慢,可以考虑将javascript文件打包在app里,当UIWebView需要加载该脚本时就从app本地读取,但UIWebView并不支持加载本地资源。下面的思路可以尝试一下:

iCab Mobile(一款iOS平台的网页浏览器)要实现一个拦截管理器来过滤页面上的广告及其他东西。它有一个简单的基于URL过滤规则的列表(通常由用户维护),当页面包含的资源(图片、js以及css等),文件的URL存在于规则列表中时,资源就不会被加载。

但看一下UIWebView类的API,会发现我们没有办法知道UIWebView正在加载什么资源,更糟的是,当你希望过滤掉某些资源文件的时候,没有方法可以强制UIWebView不去加载这些文件,

正如上面所说,实现拦截器不能靠UIWebView,因为UIWebView没有提供任何有用的API。

对UIWebView的所有请求,要找到一个能中断所有HTTP 请求的切入点,我们需要先了解一下Cocoa的URL Loading System,因为UIWebView是使用URL Loading System从web端取数据的。我们需要的切入点NSURLCache类就是URL Loading System的一部分。虽然目前iOS系统不会在磁盘上缓存任何数据(后面的iOS系统版本或许会有不同),因此在UIWebView开始加载前,NSURLCache管理的缓存数据通常为空,但UIWebView仍然会检测所请求资源文件是否存在于缓存。所以我们需要做的只是继承NSURLCache并重载其方法:

  • (NSCachedURLResponse_)cachedResponseForRequest:(NSURLRequest_)request
    UIWebView请求所有资源时都会调用这个方法。因为我们只需要在这个方法里判断请求的URL是否是我们想拦截的。如果是则创建一个没有内容的假response,否则只需调用super方法即可。

如下是实现细节:

`1.继承NSURLCache:

FilteredWebCache.h:

@interface FilteredWebCache : NSURLCache
{
}
@end`
子类的主要代码

`FilteredWebCache.m:

import "FilteredWebCache.h"

import "FilterManager.h"

@implementation FilteredWebCache
'- (NSCachedURLResponse_)cachedResponseForRequest:(NSURLRequest_)request
{
NSURL *url = [request URL];
BOOL blockURL = [[FilterMgr sharedFilterMgr] shouldBlockURL:url];
if (blockURL) {
NSURLResponse *response =
[[NSURLResponse alloc] initWithURL:url
MIMEType:@"text/plain"
expectedContentLength:1
textEncodingName:nil];
NSCachedURLResponse *cachedResponse =
[[NSCachedURLResponse alloc] initWithResponse:response
data:[NSData dataWithBytes:" " length:1]];
[super storeCachedResponse:cachedResponse forRequest:request];
[cachedResponse release];
[response release];
}
return [super cachedResponseForRequest:request];
}
@end`

首先判断URL是否需拦截(判断通过FilterManager类实现,类实现在此不列出)。如果需要,创建一个无内容的响应对象并把它存在cache中。有人可能会认为只需要返回假的响应对象就够了,没必要缓存它。但这样会因响应对象被系统释放而导致app crash。不知道为何为会这样,可能是iOS的bug(Mac OS X 10.5.x也存在同样问题,而10.4.x及更早的系统上没有问题),也可能是URL Loading System内部类之间的依赖所致。所以我们先缓存响应对象。确保所有响应都是真实存在于缓存中,这也iOS希望的,最重要的是不会crash.

更新:因为假的响应是以大于0的大小来初始化的,看起来缓存它也是必要的。

2.创建新的缓存:

接下来需要创建一个新的缓存并告诉iOS系统使用新的缓存代替默认的,这样当URL Loading System检测资源缓存时才会调用上面的代码。这要在任意UIWebView开始加载页面前做,显然应该放在app启动的时候:

NSString _path = ...// the path to the cache file
NSUInteger discCapacity = 10_1024_1024;
NSUInteger memoryCapacity = 512_1024;
FilteredWebCache *cache =
[[FilteredWebCache alloc] initWithMemoryCapacity: memoryCapacity
diskCapacity: discCapacity diskPath:path];
[NSURLCache setSharedURLCache:cache];
[cache release];
这里需要提供一个缓存存储路径。缓存文件由NSURLCache对象自动生成,我们无需事先创建文件,但要定义缓存文件所存位置(必须是应用程序“沙盒”内,如“tmp”目录或是“Document”目录)

这就是实现UIWebView基于URL进行请求过滤的所有内容,看起来其实并不复杂。

注:如果过滤规则在app运行过程中会改变,你需要从缓存中删除假的响应。NSURLCache提供了删除方法,所以这不是问题。如果过滤规则不会改变,则无需关心

Android应用架构选型(MVC MVVM MVP Flux Clean)

业务在不断推进,团队的多人协作效果并不是很好,业务内容庞大且繁杂,不同成员迥异的实现风格使得项目的维护成本越来越高,是时候做一次架构上的重构了。

大致的目标如下:

  • 易用性
    迁移的成本需要适当控制,不能给开发人员过重的额外代价,不然新架构根本推不动;可以考虑部分代码自动生成
  • 可测试性
    将UI代码与业务代码进行拆分,UI层和业务层可以分别进行单元测试 #47
  • 可维护性
    架构分层界限清晰,各个模块的实现职责都非常明确且单一
  • 可扩展性
    工程分离为平台部分和SDK部分,该部分独立实现独立维护,新增业务模块依赖SDK和基础平台进行独立开发,以独立模块的方式进行集成

目前流行的移动应用架构大致有如下几种:

模块解耦 - Android平台依赖注入框架使用(Dagger)

依赖注入(也叫做控制反转)已在一些流行的框架中(如 Spring 和 Google Guice)占有重要的位置。然而这些框架仅仅是针对标准JVM而设计的,并不支持诸如Android之类的移动环境。当RoboGuice正尝试提升Guice在Android的体验之时,Dagger通过专注于一种简化的功能集以一种不同的方式达到了更好的性能。

Dagger最早由Jake Wharton开发与维护,后来转给Google维护。

就目前来看,Dagger支持的功能仅是Google Guice的子集。考虑到这两个框架的负责人员存在重叠,所以这是可以理解的。然而,Dagger拥有更小型的配置,并且非常明确是针对Android开发的,而它最明显的不足是缺少对于方法和字段的注入支持。

Dagger牺牲了这项功能却提升了错误检查及探测方面的能力。通常依赖注入错误要等到应用开始运行期间才能得到运行时报告。Dagger却包含了注解的编译时检查,对于不完整的绑定会触发编译错误。这个功能将使得在Android上的应用开发变得更加轻松。

另一项较大的不同之处是,相比于其他流行的框架,Dagger只有较少的支持范围。Dagger仅支持@singleton注解。同样这也是可以预料的,因为Android开发的需求有别于标准的Web开发(Web开发伴随着请求和会话的范围)。

Android 应用多进程实现方案

一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。那如何让自己的应用拥有多个进程?很简单,我们的四大组件在AndroidManifest文件中注册的时候,有个属性是android:process,1.这里可以指定组件的所处的进程。默认就是应用的主进程。指定为别的进程之后,系统在启动这个组件的时候,就先创建(如果还没创建的话)这个进程,然后再创建该组件。你可以重载Application类的onCreate方法,打印出它的进程名称,就可以清楚的看见了。再设置android:process属性时候,有个地方需要注意:如果是android:process=":deamon",以:开头的名字,则表示这是一个应用程序的私有进程,否则它是一个全局进程。私有进程的进程名称是会在冒号前自动加上包名,而全局进程则不会。一般我们都是有私有进程,很少使用全局进程。

使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。(无效)

坏处的话,多占用了系统的空间,大家都这么用的话系统内存很容易占满而导致卡顿。消耗用户的电量。应用程序架构会变复杂,应为要处理多进程之间的通信。这里又是另外一个问题了。

Android里面的Deep linking

Deep Linking(深度链接)作为移动开发者可能对这个概念有点陌生,但是对于它的实现原理,说出来大家肯定都知道。Deep Linking可以唤起指定应用并向其传递数据,根据传递的数据显示特定内容页的详细信息;它不再受制于应用,只通过一个链接便可唤起应用并跳转到指定页面;它使应用之间产生了联系,使应用不再孤立存在。

FlatBuffers

为什么Android开发者应该使用FlatBuffers替代JSON?

FlatBuffers是什么?

FlatBuffers是一个高效的跨平台序列化类库,可以在C++、C#、C、Go、Java、JavaScript、PHP和Python中使用。是Google开发的,是为了应用在游戏开发,以及其他注重性能的应用上。

为什么要使用FlatBuffers?

不需要解析/拆包就可以访问序列化数据 — FlatBuffers与其他库不同之处就在于它使用二进制缓冲文件来表示层次数据,这样它们就可以被直接访问而不需解析与拆包,同时还支持数据结构进化(前进、后退兼容性)。

内存高效速度快 — 访问数据时只需要访问内存中的缓冲区。它不需要多余的内存分配(至少在C++是这样,其他语言中可能会有变动)。FlatBuffers还适合配合mmap或数据流使用,只需要缓冲区的一部分存储在内存中。访问时速度接近原结构访问,只有一点延迟(一种虚函数表vtable),是为了允许格式升级以及可选字段。FlatBuffers适合那些花费了大量时间和空间(内存分配)来访问和构建序列化数据的项目,比如游戏以及其他对表现敏感的应用。可以参考这里的基准。

灵活 — 由于有可选字段,你不但有很强的升级和回退兼容性(对于历史悠久的游戏尤其重要,不用为了每个版本升级所有数据),在选择要存储哪些数据以及设计数据结构时也很自由。

轻量的code footprint — FlatBuffers只需要很少量的生成代码,以及一个表示最小依赖的很小的头文件,很容易集成。细节上可以看上面的基准页。

强类型 — 编译时报错,而不需要自己写重复的容易出错的运行时检查。它可以自动生成有用的代码。

使用方便 — 生成的C++代码允许精简访问与构建代码。还有可选的用于实现图表解析、类似JSON的运行时字符串展示等功能的方法。(后者比JSON解析库更快,内存效率更高)

代码跨平台且没有依赖 — C++代码可以运行在任何近代的gcc/clang和VS2010上。同时还有用于测试和范例的构建文件(Android中.mk文件,其他平台是cmake文件)。

HTTPS安全在哪里?

HTTPS安全在哪里?

这篇文章很生动~

使 HTTP 后面增加一个S(Security)的技术,正是 对称加密 + 非对称加密 + CA 认证 这三种技术的混合体。当然这个主要是 HTTPS 的基本原理,真正实际中的 HTTPS 的协议是比以上的描述更为复杂一些的,并且其中任何一步稍有闪失,整个流程都将不再安全。

这也是为什么 HTTPS 协议从 SSL 1.0升级到 SSL 3.0,再被 TLS 1.0 现在被 TLS 1.3取代,其背后都是一个个细节上的优化,以防有任何闪失。

TLS 协议相比 SSL 协议增加了传输层的安全保证。

Android应用启动加速

应用启动加速并非无从下手,大致思路描述如下:

Android Instant Run

Instant Run 官方介绍
Instant Run 功能演示视频
What’s New in Android Studio 2.0

Instant Run功能可以让开发者像写html网页一样写Android原生代码,能做到一边修改代码,一边在模拟器或者实际设备上看到修改代码后的结果。iOS平台有Playground实现类似的功能。

依赖

  • Gradle 2.0.0+
  • Android Studio Instant Run开关
    Settings->Build,Execution,Deployment->Instant Run--->enable section √ (常见问题1:应用build-安装后启动报错)

image
看到运行符号旁边的闪电就可以了。

运行
模拟器打开要修改的目标页面 - 修改目标页面的代码 - Instant Run.

局限
当前Instant Run仅仅适用于布局的修改。即我们可以把一次修改到运行看作一个“周期”,在这个周期里面你仅仅修改了xml布局文件,或者说和逻辑代码不相关的文件,那么你点击运行的时候才会触发Instant Run,否则的话,Android Studio还是依然会重新编译运行。对此,官方文档的说明如下:

Not all code changes are supported by Instant Run currently.
Here are some code changes that Instant Run does not currently support:

  • Add/remove/change
  • annotations
  • Add/remove/change
  • an instance field
  • Add/remove/change a static field
  • Add/remove a static method signature
  • Change a static method signature
  • Add/remove an instance method
  • Change an instance method signature
  • Changing which parent class the current class inherits from
  • Change the list of implemented interfaces
  • Changing static initializer of a class

Here is the current list of supported code change scenarios:
screen shot 2016-04-28 at 10 12 05 am

Over the coming months, we plan to expand the Instant Run enable more change types, and continue to make your edit, build, run cycle faster.

Objective-C Tips for Good

Objective-C语言并不直接操作对象,而总是借助指针。事实上,当我们提到Objective-C语言中的『对象』时,我们往往指的是『指向对象的指针』;但是由于我们总是通过指针来操作对象,所以就简称为『对象』了。『对象总是借助指针被操作

Android Dex分包处理

Dex分包处理。第一次开启App的时候 install dex + dexopt 时间很长,所以第一次开启的时候另启进程专门做这个事情,防止主线程因为时间长而发生ANR。至于自己去配置主dex是为了以防自动分包ClassNotFound异常。

待分析开源项目https://github.com/yydcdut/PhotoNoter

移动跨平台设计方案开源动态跟踪

构建F8 App / React Native开发指南

在 2015 年的 F8 会议上,React Native for Android 发布。这一年的 F8 app iOS 版本是用 React Native 开发的,而 Android 版本还是原生开发。 在这年之前,iOS 和 Android 都是原生开发。React Native for Android 发布,意味着我们有机会削减 app 的业务逻辑和 UI 代码了。一些 Facebook 的团队使用 React Native,重用了大约 85% 的代码 。

React Native 还使得可以和 UI 设计师一起进行可视化组件的快速原型设计。

http://f8-app.liaohuqiu.net/tutorials/building-the-f8-app/planning/

Android任务列表中滑动删除应用后都发生了什么?

简单来说,这和多次按返回键退出应用一样,系统会杀掉后台进程,但优势也不是这样。
从最近任务中移除一个条目会移除这个app存在的后台进程。但是它并不会直接结束service,当他们在任务列表中被清除的时候,其实他们自己有相应的api(onTaskRemoved被调用)处理service是否应当被结束。也就是说,你使用的e-mail接收的app即使你在任务列表中把它清除了,它的service也会接收e-mail信息。
当然如果你想要完全停止一个app,你可以通过设置->应用管理 ->进入应用信息页面,点击强制退出。强制退出会让该app的所有进程被杀掉,所有的service停止,所有的通知被移除,所有的提醒被关闭等。该app除了被再次调用的情况下,不会再被启动。
也就是说,是由app来决定在任务列表清楚的时候,后台进程是否被杀掉。

what-actually-happens-when-you-swipe-an-app-out-of-the-recent-apps-list

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.