如有错漏请不吝拍砖指正,转载请注明出处,非常感谢
转自:http://blog.csdn.net/silenceburn/archive/2010/12/18/6083375.aspx
有一个问题,在网上被频繁的问到,就是为什么自定义的Receiver总是无法接收到SD卡插拔的事件。
而此问题大部分情况下可以通过增加一句代码解决: filter.addDataScheme("file"); // filter是IntentFilter对象
那么为什么增加这句代码就可以解决了呢?这个问题尽管有人问到,但是却没有太好的回答。
可能是因为对于精通IntentFilter策略的高手们来说,这根本算不上问题,是一个再明显不过的事实而已。
而对于不太了解IntentFilter策略的我们初学者来说,这个问题又暂时有点太难以理解吧。
因此,本文试着通过对android的事件过滤策略进行介绍和分析,结合示例程序进行验证,
来解答此问题,并浅显的介绍android事件过滤策略。
1. 编写示例程序,创建一个自定义的BroadcastReceiver
首先我们创建一个android工程起名为SdCardTester,作为示例程序。
为了方便在后续步骤中模拟SD卡插拔,建议将目标平台设定为2.3版本,使用2.3版本的模拟器。
此外务必注意,运行此示例程序的AVD模拟器需要增加SD卡功能支持。
然后为SdCardTester类增加一个BroadcastReceiver类型的成员变量 mReceiver。
在onCreate中,使用匿名类的技巧,为 mReceiver 赋值一个BroadcastReceiver子类实例。
-
mReceiver =
new
BroadcastReceiver() {
-
@Override
-
public
void
onReceive(Context context, Intent intent) {
-
Log.i("myLoger"
,
" Receive SDCard Mount/UnMount!"
);
-
}
-
;
注意代码中重写的onRecevie函数里只有一句代码,用于记录日志。以证明我们确实收到了事件。
然后创建一个IntentFilter,用于过滤SD卡插拔事件。
最后把我们自定义的Receiver和编写好的IntentFilter注册到系统中
-
IntentFilter filter =
new
IntentFilter();
-
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-
registerReceiver(mReceiver, filter);
最后的最后不要忘了在onDestory中注销我们的自定义Receiver,
至此完成了示例程序的代码编写,SdCardTester的完整代码如下:
-
package
com.silenceburn;
-
-
import
android.app.Activity;
-
import
android.content.BroadcastReceiver;
-
import
android.content.Context;
-
import
android.content.Intent;
-
import
android.content.IntentFilter;
-
import
android.os.Bundle;
-
import
android.util.Log;
-
-
public
class
SdCardTester
extends
Activity {
-
-
BroadcastReceiver mReceiver;
-
-
-
@Override
-
public
void
onCreate(Bundle savedInstanceState) {
-
super
.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
-
mReceiver = new
BroadcastReceiver() {
-
@Override
-
public
void
onReceive(Context context, Intent intent) {
-
Log.i("myLoger"
,
" Receive SDCard Mount/UnMount!"
);
-
}
-
};
-
-
IntentFilter filter = new
IntentFilter();
-
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-
registerReceiver(mReceiver, filter);
-
-
}
-
-
@Override
-
protected
void
onDestroy() {
-
-
super
.onDestroy();
-
unregisterReceiver(mReceiver);
-
}
-
}
2. 测试示例程序
运行SdCardTester,等看到hello World 字样,说明onCreate完成,也就意味着我们自定义的Receiver也已经启动了。
之后,不要用BACK退出,按HOME按钮返回主屏幕,(也就是要保证我们的自定义Receiver仍然在运行)
进入手机设定,选择Storage (如果系统语言选择为中文了是“存储”),
选择 Unmount SD card / mount SD card 选项,就可以模拟SD卡插拔的动作了。如下图所示:
如果我们的自定义Receiver收到了相关事件,按照代码实现,就会使用 TAG "myLoger" 输出日志到logCat。
因此我们通过观察logCat输出确定是否有相关事件发生,在cmd窗口中运行 " adb logcat -s myLoger:i " ,即可持续监控日志输出。
或者使用Eclipse ADT插件增加的DDMS视图,在logCat 的View中增加一个filter,如下图所示:
注意,按照我们当前的代码实现,无论我们如何插拔SD卡,都不会看到日志窗口监控到事件发生。
OK,我们现在增加那行神奇的代码:“ filter.addDataScheme("file"); ”,
并在onCreate中增加一个日志输出监控程序进入。修改之后的代码如下:
-
package
com.silenceburn;
-
-
import
android.app.Activity;
-
import
android.content.BroadcastReceiver;
-
import
android.content.Context;
-
import
android.content.Intent;
-
import
android.content.IntentFilter;
-
import
android.os.Bundle;
-
import
android.util.Log;
-
-
public
class
SdCardTester
extends
Activity {
-
-
BroadcastReceiver mReceiver;
-
-
-
@Override
-
public
void
onCreate(Bundle savedInstanceState) {
-
super
.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
Log.i("myLoger"
,
" onCreate ......"
);
-
-
mReceiver = new
BroadcastReceiver() {
-
@Override
-
public
void
onReceive(Context context, Intent intent) {
-
Log.i("myLoger"
,
" Receive SDCard Mount/UnMount!"
);
-
}
-
};
-
-
IntentFilter filter = new
IntentFilter();
-
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-
-
filter.addDataScheme("file"
);
-
-
registerReceiver(mReceiver, filter);
-
-
}
-
-
@Override
-
protected
void
onDestroy() {
-
-
super
.onDestroy();
-
unregisterReceiver(mReceiver);
-
}
-
}
修改完成再次运行程序,不要用BACK退出,按HOME按钮返回主屏幕,进入Setting模拟SD卡插拔,
然后观察logCat日志监控窗口,神奇的事情发生了,我们可以接收到事件了!如下图所示:
3.事件(Intent)的分类:显式 和 隐式
那么,为什么加上 filter.addDataScheme("file"); 就可以了呢?
为了解决这个问题,我们要先学习Intent的分类。Intent分为两大类,显式和隐式。
显式事件,就是指通过 component Name 属性,明确指定了目标组件的事件。
比如我们新建一个Intent,指名道姓的说,此事件用于启动名为"com.silenceburn.XXXX”的Activity,那么这就是一个显式事件。
隐式事件,就是指没有 component Name 属性,没有明确指定目标组件的事件。
比如系统向所有监控通话情况的程序发送的“来电话了!”的事件,由于系统不确定谁会处理这个事件,
因此系统不会明确指定目标组件,也就是说没有目标组件,那么这就是个隐式的事件。
此处只是简介显式和隐式事件,更精确详细的描述请查阅SDK文档,
我们只需要记住一点,两种事件的最大区别是 component Name 属性是否为空。
4.事件过滤策略 和 IntentFilter
系统在传送显式事件时非常方便,因为如果把Intent比作一封信,那么component Name就是一个详细的收件人地址,
系统可以精确的把显式事件送达目标组件。
而传送隐式事件时,就比较麻烦了。因为这封信的信封上,没有写收信地址!
那怎么办呢?系统做了一个艰难的决定,就是把信拆开看看。通过信件内容里面的线索,去寻找合适的收件人。
比如信中的线索描述到:“收信人是男性,快30岁了,未婚,喜欢玩游戏”,那么系统就在小区里面去找这样的人。
非常值得庆幸的事情是,这个小区的人素质非常高,每户人家都写了点自我介绍在门口,
比如张三写道:“我是男性,90后,未婚,喜欢玩游戏”,李四写道:“我是女性,快30岁了,未婚,喜欢逛街”等等等等。
有了每户人家的自我介绍,系统就能很快的定位真正的收件人了!
上面是一个类比的例子,不过android系统处理隐式事件的策略,基本上就是上述这种模式了。
首先系统会通过观察Intent的内容(打开信件看内容),取得匹配线索,系统所需的线索是如下三种 :
action
data (both URI and data type)
category
其次,系统中每个组件,如果想收取隐式事件,则必须声明自己的IntentFilter(自我介绍,我对什么样的信件感兴趣)。
至于怎么写IntentFilter,已经相当明了了,那就是应该是这样写:
"我是组件XXXX,我想要接收这样的隐式事件:它的ACTION必须是 XXX,它的 category 必须是 YYYY ,它包含的data必须是ZZZZ "
如果组件不声明IntentFilter,那么所有的隐式事件都不会发送给该组件。(注意,这并不影响向该组件发送显式事件。)
对于系统中发生的每个隐式事件,系统都会尝试将 action, data , category 和系统中各个组件声明的 IntentFilter 去进行匹配,
以找到合适的接收者。
上述是android系统的事件过滤策略的简单原理,实际情况远比这要复杂,考虑本文的目的,此处不再展开,SDK文档中都有详尽描述。
5. 分析SD卡插拔事件
由上节可知,对于显式事件,系统可以精确送达。对于隐式事件,系统分析事件的 action, data , category 内容,
并和各个组件声明的IntentFilter进行匹配,找出匹配的组件进行送达。
因此SD卡插拔事件能否被我们自定义的Recevier收到就取决于如下子问题了:
1. SD卡插拔事件是显式事件,还是隐式事件
2. SD卡插拔事件的action, data , category 的内容是什么
3. 我们自定义的Receiver组件的IntentFilter是如何声明的
为了解决上述3个问题,我们修改一下代码,将SD卡插拔事件的内容打印到logcat中进行观察。
修改后的代码如下:(注意这里我们要添加好 filter.addDataScheme("file"); 以确保事件可以被接收到)
-
package
com.silenceburn;
-
-
import
android.app.Activity;
-
import
android.content.BroadcastReceiver;
-
import
android.content.Context;
-
import
android.content.Intent;
-
import
android.content.IntentFilter;
-
import
android.os.Bundle;
-
import
android.util.Log;
-
-
public
class
SdCardTester
extends
Activity {
-
-
BroadcastReceiver mReceiver;
-
-
-
@Override
-
public
void
onCreate(Bundle savedInstanceState) {
-
super
.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
Log.i("myLoger"
,
" onCreate ......"
);
-
-
mReceiver = new
BroadcastReceiver() {
-
@Override
-
public
void
onReceive(Context context, Intent intent) {
-
-
Log.i("myLoger"
,
"Component: "
+ intent.getComponent());
-
-
Log.i("myLoger"
,
"Aciton: "
+ intent.getAction());
-
Log.i("myLoger"
,
"Categories: "
+ intent.getCategories());
-
-
Log.i("myLoger"
,
"Data: "
+ intent.getData());
-
Log.i("myLoger"
,
"DataType: "
+ intent.getType());
-
Log.i("myLoger"
,
"DataSchema: "
+ intent.getScheme());
-
-
Log.i("myLoger"
,
" Receive SDCard Mount/UnMount!"
);
-
}
-
};
-
-
IntentFilter filter = new
IntentFilter();
-
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-
-
filter.addDataScheme("file"
);
-
-
registerReceiver(mReceiver, filter);
-
-
}
-
-
@Override
-
protected
void
onDestroy() {
-
-
super
.onDestroy();
-
unregisterReceiver(mReceiver);
-
}
-
}
OK,让我们再次运行程序,通过Setting模拟插拔SD卡,观察logCat的输出情况。
下图是挂载SD卡时的日志输出情况:
通过日志输出我们可以得知挂载SD卡事件的 Componet 是null ,因此它是一个隐式事件。
因此能否送达,需要看事件的 action, data , category 和 IntentFilter是否匹配。
它的ACTION是 android.intent.action.MEDIA_MOUNTED,
和我们定义的IntentFilter的 filter.addAction(Intent.ACTION_MEDIA_MOUNTED); 语句相匹配。
因此action部分是匹配的。
它的Categories是null,而我们定义的 IntentFilter 也没有使用addCategory方法增加category定义,
null == null,因此 categories也是匹配的。
action, data , category 中的两个要素已经匹配,那么能否匹配成功的关键,就是看data是否匹配了。
6. data匹配规则
首先务必认识到,data是一个相对复杂的要素。 data由URI来描述和定位,URI由三部分组成,
scheme://host:port/path 模式://主机:端口/路径
例如我们截获的挂载SD卡事件,它的data的URI是 file:///mnt/sdcard
其中模式部分是 file , 主机:端口部分是空的, path部分是 mnt/sdcard
此外在事件中,还可以设置data的MIME类型,作为事件的datatype属性。
综上所述,data是一个较复杂的要素,因此其匹配规则也格外复杂,
首先明确一个匹配原则,就是对于URI的匹配,只比较filter中声明的部分。
部分匹配原则:只要filter中声明的部分匹配成功,就认为整个URI匹配成功。
举例来说, content://com.silenceburn.SdCardTester:1000/mydata/private/
和
filter定义为 content://com.silenceburn.SdCardTester:1000/
是可以匹配的。
注意filter中并没有定义path部分,但是依然可以匹配成功,因为filter不声明的部分不进行比较。
换句话讲,任何符合content://com.silenceburn.SdCardTester:1000/的事件,无论path是什么,都可以匹配成功。
接下来是真正的data部分的,也就是URI的匹配规则如下:
1. 如果data的URI和datatype为空,则 filter 的URI和type也必须为空,才能匹配成功
2. 如果data的URI不为空,但是datatype为空,则 filter 必须定义URI并匹配成功,且type为空,才能匹配成功
3. 如果data的URI为空,但是datatype不为空,则 filter 必须URI为空,定义type并匹配成功,才能匹配成功
4. 如果data的URI和data都不为空,则 filter 的URI和type都必须定义并匹配成功,才能匹配成功。
对于URI部分,有一个特殊处理,就是即使filter没有定义URI,content和file两种URI也作为既存的URI存在。
(举个例子,对于 content 和 file 两种模式的data,只要filter定义的datatype可以和事件匹配,就认为匹配成功,
filter不需要显式的增加 content 和 file 两种模式,这两种模式内置支持 )
有了规则,有了对SD卡插拔事件的内容的分析,我们就可以按图索骥照章办事了。
7.SD卡插拔事件的匹配
首先如第6节所述,SD卡插拔是一个隐式事件,而且 action 和 category 部分和我们的 filter 均可以匹配成功。
其data部分的URI为 file:///mnt/sdcard
,datatype为 null ,因此应用第6节比较规则中的 2 号规则:
2. 如果data的URI不为空,但是datatype为空,则 filter 必须定义URI并匹配成功,且type为空,才能匹配成功
我们的filter中没有使用 addtype 方法 ,因此 filter 的type为空, datatype部分匹配成功。
data的URI为file:///mnt/sdcard
,我们使用 filter.addDataScheme("file"); 语句定义 schema 为 file,
根据部分匹配规则,data匹配成功。
至此,整个事件匹配成功,至此,我们就明白了文初的问题,为什么必须添加 filter.addDataScheme("file"); 语句才能收到事件!
我们可以尝试把 filter.addDataScheme("file"); 后面增加语句
-
filter.addDataPath(
"mnt/sdcard"
, PatternMatcher.PATTERN_LITERAL);
依然可以匹配成功,收到SD卡插拔事件。因为这样就组成了一个URI的完全匹配。
我们可以尝试把给 filter 增加 datatype 属性,
-
try
{
-
filter.addDataType("text/*"
);
-
} catch
(MalformedMimeTypeException e) {
-
-
e.printStackTrace();
-
}
这样就无法匹配成功了。因为SD卡插拔事件的datatype是null,
而我们定义的filter的datatype是MIME"text/*" 。
总结
至此文初的问题解析完毕。老生常谈,事实上android平台的intentFilter处理机制远远复杂于本文所述范围。
特别是本文对action和category两种要素的讨论非常少几乎没有,实际上这两种要素的处理也是比较复杂的。
本文只是冰山一角的讲述了了一些基本原理和基本准则。
IntentFilter机制作为android平台的重要基础知识之一,我们大家要一起继续努力学习,和大家共勉 :)
分享到:
相关推荐
【资源说明】 基于AT89C51单片机的三电梯联动控制系统+全部资料+详细文档(高分项目).zip基于AT89C51单片机的三电梯联动控制系统+全部资料+详细文档(高分项目).zip基于AT89C51单片机的三电梯联动控制系统+全部资料+详细文档(高分项目).zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
梯度下降算法,介绍梯度下降算法 实例说明其运行原理,供学习参考。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
【资源说明】 基于51单片机的空气检测+DS1302时钟显示+全部资料+详细文档(高分项目).zip基于51单片机的空气检测+DS1302时钟显示+全部资料+详细文档(高分项目).zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
西北工业大学-电子实习报告.pdf
罗兰贝格:供应链优化方案-企业采购战略(最终报告)(ppt-112).ppt
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
VR(Virtual Reality)即虚拟现实,是一种可以创建和体验虚拟世界的计算机技术。它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真,使用户沉浸到该环境中。VR技术通过模拟人的视觉、听觉、触觉等感觉器官功能,使人能够沉浸在计算机生成的虚拟境界中,并能够通过语言、手势等自然的方式与之进行实时交互,创建了一种适人化的多维信息空间。 VR技术具有以下主要特点: 沉浸感:用户感到作为主角存在于模拟环境中的真实程度。理想的模拟环境应该使用户难以分辨真假,使用户全身心地投入到计算机创建的三维虚拟环境中,该环境中的一切看上去是真的,听上去是真的,动起来是真的,甚至闻起来、尝起来等一切感觉都是真的,如同在现实世界中的感觉一样。 交互性:用户对模拟环境内物体的可操作程度和从环境得到反馈的自然程度(包括实时性)。例如,用户可以用手去直接抓取模拟环境中虚拟的物体,这时手有握着东西的感觉,并可以感觉物体的重量,视野中被抓的物体也能立刻随着手的移动而移动。 构想性:也称想象性,指用户沉浸在多维信息空间中,依靠自己的感知和认知能力获取知识,发挥主观能动性,寻求解答,形成新的概念。此概念不仅是指观念上或语言上的创意,而且可以是指对某些客观存在事物的创造性设想和安排。 VR技术可以应用于各个领域,如游戏、娱乐、教育、医疗、军事、房地产、工业仿真等。随着VR技术的不断发展,它正在改变人们的生活和工作方式,为人们带来全新的体验。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
【采购管理】采购管理规范性培训(PDF70页).pdf
VR(Virtual Reality)即虚拟现实,是一种可以创建和体验虚拟世界的计算机技术。它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真,使用户沉浸到该环境中。VR技术通过模拟人的视觉、听觉、触觉等感觉器官功能,使人能够沉浸在计算机生成的虚拟境界中,并能够通过语言、手势等自然的方式与之进行实时交互,创建了一种适人化的多维信息空间。 VR技术具有以下主要特点: 沉浸感:用户感到作为主角存在于模拟环境中的真实程度。理想的模拟环境应该使用户难以分辨真假,使用户全身心地投入到计算机创建的三维虚拟环境中,该环境中的一切看上去是真的,听上去是真的,动起来是真的,甚至闻起来、尝起来等一切感觉都是真的,如同在现实世界中的感觉一样。 交互性:用户对模拟环境内物体的可操作程度和从环境得到反馈的自然程度(包括实时性)。例如,用户可以用手去直接抓取模拟环境中虚拟的物体,这时手有握着东西的感觉,并可以感觉物体的重量,视野中被抓的物体也能立刻随着手的移动而移动。 构想性:也称想象性,指用户沉浸在多维信息空间中,依靠自己的感知和认知能力获取知识,发挥主观能动性,寻求解答,形成新的概念。此概念不仅是指观念上或语言上的创意,而且可以是指对某些客观存在事物的创造性设想和安排。 VR技术可以应用于各个领域,如游戏、娱乐、教育、医疗、军事、房地产、工业仿真等。随着VR技术的不断发展,它正在改变人们的生活和工作方式,为人们带来全新的体验。
【资源说明】 基于单片机和控客的远程控制站点+全部资料+详细文档(高分项目).zip基于单片机和控客的远程控制站点+全部资料+详细文档(高分项目).zip基于单片机和控客的远程控制站点+全部资料+详细文档(高分项目).zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
【资源说明】 基于51单片机的心形流水灯包括原理图,PCB图,仿真图,程序代码;PS原理图与PCB图请用立创EDA打开;+全部资料+详细文档(高分项目) 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
【资源说明】 基于51单片机的万年历电子钟设计+全部资料+详细文档(高分项目).zip基于51单片机的万年历电子钟设计+全部资料+详细文档(高分项目).zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
西北工业大学-模拟电子技术基础 - 中国大学mooc.doc