欢迎来到58原创网网
更新日期:2025-09-06 23:56
写作核心提示:
写一篇关于《Crash》(《撞车》)的英语观后感作文,需要注意以下几个关键事项,以确保你的作文有深度、结构清晰且表达准确:
1. "明确中心思想 (Clear Central Theme):" 《Crash》这部电影探讨了非常复杂且深刻的主题,如种族歧视、阶级差异、暴力循环、沟通障碍、欲望失控等。你需要先确定你最想表达或感受最深的主题是什么。 是关于不同文化/种族间难以逾越的隔阂?还是关于个人行为如何无意中伤害他人并引发连锁反应?或是关于欲望如何驱使人做出错误选择?明确中心能指导你的整个作文。
2. "抓住关键情节和细节 (Focus on Key Plot Points and Details):" 选择与你的中心思想最相关的几个关键情节或场景来展开论述。例如,如果你想谈种族歧视,可以分析白人警察对亚裔司机的不公对待,以及不同家庭因种族背景而产生的冲突。 不要试图涵盖所有情节,那样会使文章显得杂乱无章。选择几个有力的例子,并深入分析它们如何支持你的观点。
3. "深入分析而非简单复述 (Analyze, Don't Just Summarize):" "观后感 (Reflection)" 的关键在于“分析”和“反思”。不要仅仅罗列发生了什么(这更像剧情梗概
《我的世界》Minecraft想必每个人都玩过,但是Minecraft曾发布的官方小说你可曾看过呢?毕竟很多还是英文原版的小说,对于不少玩家而言还是有一定门槛的。既然咱们没有全部读过,不妨就来看看这些小说究竟有什么吸引人的地方。
第一部:我的世界:海岛(Minecraft: The Island)
自2017年《我的世界》开启了官方小说的元年,这部小说目前是有中文版的。主要说的是主角是一个现实世界的人,但是却流落在了一座方块世界的孤岛上,他失忆了,但是却悟出了只有熟悉这个世界的规则才能活下去。所以他想要揭开这座海岛,这个世界的秘密。
第二部:《我的世界:破碎》(Minecraft: The Crash)
这本小说同样也是有简体中文版的,故事同样发生在现实世界。一场车祸Bianca几近瘫痪,在VR版《我的世界》中他重新控制了自己的身体,找到了新的朋友。一个非常经典的美式剧本中自我救赎的故事。
第三部:《我的世界:失落的日记》(Minecraft: The Lost Journals)
故事本身是架空的,发生在《Minecraft》这个世界当中,主角意外发现了一本旧日记,循着日记中的描述进入了下界,他们想要找到这本日记的主人,所以冒险、成长、友谊、亲情是这本书的核心主题。
第四部:《我的世界:末地》(Minecraft: The End)
这一次主角不再是普通的人类,而是末影人兄妹,末地是他们生存和生活的地方,也是他们的家。直到来自主世界的人类计划入侵末地,杀死末影龙,掠夺财富。兄妹俩为即将到来的战争做了充足的准备,但真相真是这样么?
第五部:《我的世界:远航》(Minecraft: The Voyage)
故事从一个Minecraft的“建筑师”开始,这个世界不是每个人都喜欢冒险的,休闲生存又有何不可?然而在一次袭击事件中,建筑师的家园被破坏了,自己也流落到了荒岛上。在寻找家的路上,他发现了主世界原来是一个拥有如此精彩的世界。
第六部:《我的世界:沉船》(Minecraft: The Shipwreck)
故事从现实世界的托马斯开始(托马斯显然不是火车),他因父亲工作而经常搬家,没有朋友。一次意外在一个旧电脑上发现了一个神秘的服务器,在神秘的巫师引导下,踏上了《我的世界》最危险的海洋深处......
第七部:《我的世界:山》(Minecraft: The Mountain)
注意,这部小说是第一部《海岛》的续集,主角离开了孤岛之后,在夜幕中僵尸的追赶之下逃亡到了山上,在这里他第一次遇见了真正的人类,孤独不再是主旋律,朋友、团队、合作,才是接下来的生存之路。
第八部:《我的世界:末影龙》(Minecraft: The Dragon)
这一次主角是一位来自Minecraft世界沙漠村庄的女巫,为了保护村庄免受灾厄村民的袭击,她外出寻求帮助。但意外知道了一枚末影龙的蛋,每有人知道当蛋孵化后末影龙是会帮助村庄抵御外敌,还是彻底毁灭村庄!
第九部:《我的世界:怪物小队》(Minecraft: Mob Squad)
在Minecraft的主世界有个被巨大围墙所保护的镇子,叫作“聚宝盆镇”,这里资源丰富、生活安逸。直到有一天怪物闯进了镇子。主角和伙伴决心违背世代祖训离开这里,寻找拯救家园的方法。
第十部:《我的世界:避风港试炼》(Minecraft: The Haven Trials)
避风港试炼是一个Minecraft服务器的名字,所以故事当然就来自真实的世界。主角茜茜的好朋友留下了“我们要搬走了”一个消息,就彻底离开了她的世界。为了寻回好友,茜茜进入了一个名为避风港试炼的服务器,在这里她将克服重重阻碍才可以和好友相聚。
第十一部:《我的世界:怪物小队》II
这是第九部“怪物小队”的续作,怪物小队的四个小冒险家解救了村庄,村庄不再与世隔绝。但在大人眼中,他们终究还只是孩子。直到有一天小队中的一名成员突然离奇消失了,他们又将重新踏上解救朋友的旅程。
第十二部:《我的世界:僵尸》Minecraft: Zombies!
僵尸三部曲的第一部:平原小镇中的日子优先而安逸,Bobbie是姐姐,Johnny是弟弟。有一天一位大恶人Logan的到来,引来了大量的僵尸。村庄被毁,村民全死了。姐姐带着被僵尸咬伤的弟弟幸存,或许冒险家Ben有办法救活自己的弟弟......
第十三部:《我的世界:怪物小队》III
怪物小队第三部,不要害怕苦力怕。讲述的是,怪物小队在墙外继续冒险,他们被一群戴着“苦力怕”头颅的人给跟踪了?PS:这个怪物小队的作者还真能写啊~
第十四部:《我的世界:红石城堡》(Minecraft: Castle Redstone)
主角的父亲是一位优秀的冒险家,走遍了世界杀死了末影龙。为了可以成为父亲那样的英雄,主角找到了一张神秘的地图,地图通向一座古代的神秘遗迹“红石城堡”,冒险之旅就此开始了!
第十五部:《我的世界:僵尸!》II(Minecraft: Zombies Return!)
僵尸三部曲中的第二部,目前还未发布,预计今年7月份发行。故事说的是姐姐Bobbie试图阻止恶人Logan更大的阴谋,冒险家Ben负责驯化已经僵尸化的弟弟。在一本恶人的日记中记载了接下来的他邪恶的目标,杀死英雄Peggy。接下来,姐姐、僵尸弟弟、还有贫穷的冒险家Ben,他们能成功阻止这个巨大的阴谋么?
在这《我的世界》整整15部官方小说中,僵尸三部曲系列是最对胃口的,一只已经僵尸化的人类是怎样训练出可以不咬人的呢?
React Native(简称RN)是Facebook于2015年开源的移动端跨平台开发框架。RN从开源以来已经有6个年头了,有着十分丰富的社区资源和生态,时至今日依然有很多移动端项目都使用RN来开发。本文主要通过以往的项目实践来谈谈在选择RN开发app可能需要注意的一些点,也算是自己的一个踩坑经验总结。
跨平台开发框架都是有局限性的,这一点RN也不例外,RN本身还是要使用原生API来实现UI的绘制,JS bridge的创建和与原生平台的通信都需要消耗资源,基于这样的前提,RN开发的应用相对于原生平台来说往往会占用更多的内存和CPU,因此而出现的卡顿、掉帧的概率也会更高,进而对用户体验造成较大的影响。
那么问题来了,RN真的很差、不适合工程实践吗?
这个问题就涉及到技术选型了,是否应该用RN?什么样的情况下适合使用RN作为首选开发技术?
我个人认为需要从以下几个方面考虑:
面向C端的产品一般最好还是使用原生开发技术,性能稳定性相对会更加可靠一些,尤其是这款产品的市场期望比较高,对用户和市场规模增长有比较大的期待时。性能更好、更加稳定可靠的技术应当是首选,这样会带来更好的用户体验。当然如果用户数量比较少,app应用场景比较单一的情况不太需要这样的考虑,比如功能并不复杂的工具类应用。
很多app都使用原生与H5的Hybrid模式开发,但是H5的体验跟原生相比差距较大,RN的体验比H5就要好很多,而且RN还具有热更新的能力,这对于需要频繁更新内容的业务来说是一个不错的选择。比如像图书、漫画这种内容上新比较频繁或者UI排版更迭频繁的更适合用RN,像以音视频播放为主这种追求性能稳定的就不太合适了。
团队规模比较小,开发周期短的情况下尽量选择熟悉的技术栈,能够节省时间。
这一点需要考虑到团队是否有相应的技术,比如如果团队没有Android或iOS原生开发的技术,都只有web前端开发,又需要做app,那么可以考虑RN,尤其是有React技术储备的情况。
这一点一般来说考虑的优先级是最低的,开发团队可能很少会考虑维护的问题,因为交付之后项目谁维护、要不要维护都是个问题。作为跨平台开发框架来说,RN通常可能需要维护Android和iOS两端,尤其是app应用场景和功能比较复杂的情况下,与原生交互的部分就少不了,对于纯web前端开发来说是个不小的挑战,需要一个人负责两个平台的维护工作。总之,RN一个开发者维护的情况下,那么对开发者的要求是需要兼顾Android和iOS两个平台,这也是为什么说学了RN迟早安卓和iOS都要学。如果是原生开发,可能需要两个人维护,一人一个平台,就会提高维护成本。
综上,RN到底适不适合在项目中实践,最好按实际情况考虑。我个人觉得RN还是不错的,性能表现由于先天性的架构设计问题与原生有差距是正常的,但是也没有差到无法用的地步,这一点不能人云亦云。
RN项目中经常会用到很多第三方库,比如路由框架react-navigation、数据存储AsyncStorage、状态管理react-redux等等。在项目维护时我们可能会面临第三方库的升级带来的一系列问题、某些library没人维护了,但是我们出于某些原因还需要继续使用等等,针对这些情况谈谈我的理解。
适时升级的意思就是第三方库有新版本的时候,在保持app稳定性、不引起regression问题的情况下尽可能的升级第三方库。在app的迭代中把第三方库的升级维护考虑进去是很有必要的,以我所在的项目为例:
我们项目中使用的react-navigation版本非常老旧了,还停留在v2版本,而最新的react-navigation实际已经到了v5版本,并且v5版本中对核心功能组件进行了拆分,意味着v5以后需要安装react-navigation的多个依赖包。react-navigation一直都是一个API变动非常大的router库,每一个大版本的迭代都可能导致原来的路由用法发生改变。对比老旧的v2版本来说,升级到新版本是更好的选择,功能和性能更强、路由灵活性更高,但是在我接手项目之前react-navigation一直都没升级过,直接升级到最新版本变动太大了,风险太高,容易引起功能上的bug。如果在之前的迭代中能把这块升级的工作考虑进去,随着每个迭代一起去做,改动会相对较小,就能平稳过渡到新版本。
没人维护的库怎么处理,分几种情况:
- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage ;
} else {
;
}
}
从我们的项目来看,升级到RN 0.63版本会导致react-navigation老版本中的依赖库
react-native-safe-area-view报错。所以连带的也需要升级react-navigation,但我上面提到升级react-navigation风险比较大,需要比较大的effort去做,所以这里我还是保持RN版本小于0.63,通过react-native-fix-image来修改iOS源码或者用patch-package打patch实现,做法虽然丑陋了点,但可以最小的effort先解决问题,后续再用更稳妥的方式逐步升级RN和react-navigation版本。
总之,RN和第三方依赖库版本太老长时间不升级会带来很多问题,如老API过时、新API变动太大,iOS、Android系统更新带来的兼容性问题都需要解决,升级应该作为一个task经常关注并适时执行。
Realm是一个开源的移动端数据库,性能表现非常不错,API也简单易用。但RealmJS真是太难用了,首先安装就很费劲,经常安装失败,即使安装成功,按照文档配置好了iOS也经常报错Missing Realm Constructor,并且这个错误问题还偶尔在production环境出现,导致app直接白屏无法使用。
而且在iOS 14beta版中RealmJS引发了一个crash,导致所有iOS 14beta版的用户都受到影响,虽然说这个crash在iOS 14的beta2迭代中就不存在了,但为了保险起见,我还是决定升级library。为此我曾尝试升级到v6.6版本,作为一个暂时的解决方案,但是安装依赖失败这一点简直不能忍,于是我决定彻底抛弃RealmJS,改用Realm的native SDK。虽然在Android和iOS两端都需要写native代码来实现存储功能,但真的比RealmJS用起来容易多了,再也不用担心打包失败和missing constructor了,真的谁用谁知道!
RN对原生平台依赖太强,取代不了原生。虽然它已经能做很多事了,但是:
既然根植于原生,必然是脱离不了原生平台的。很多功能使用原生方案实现是更好的选择,比如拍照、图片编辑、动画使用原生API实现更直接、性能表现更好。
Android和iOS系统更新或者条款更新总会需要开发者做一些适配工作,比如Android 10存储权限的变更,导致共享目录在Android 10以后不能再直接访问,WRITE_EXTERNAL_STORAGE权限也不起作用。我们项目中用到第三方库rn-fetch-blob来做下载功能,但是由于此库无人维护,只能自己适配。由于下载和存储是在Native端实现的,只能在Native端去做改动。此外,对于iOS来说,要适配更新的iOS系统,我们经常需要升级Xcode,可能在新版本的Xcode上就会遇到原来能编译通过的项目现在却编译失败了。
RN需要JS的运行环境,在开发模式下本地需要启动一个package server来监控文件的变更,配合chrome或者react dev tools来调试JS代码。Native代码仍然需要使用Android studio或者Xcode来调试,这无疑增加了调试工作量。让人难受的是有时候会因为环境问题或者第三方库的原因导致频繁出现红屏报错,为了解决这些error需要各种search,时间就耗在这些问题上了。
RN打包时会把JS代码和资源文件打包成一个js bundle文件,这个bundle文件中就包含了所有编译之后的JS代码,因此一些重要的配置信息如API key、secret等最好不要写在JS代码中,以免造成安全问题。官方文档也针对security做了比较清楚的说明。
RN的稳定性与原生平台是有差距的,这一点必须承认,尤其是在Android端。RN需要JS的运行环境来解释执行JS编译之后的bundle文件,在Android端使用了webkit官方开源的jsc.so,此外还有很多其它的so调用,比如Android系统的libc.so。一些crash问题就是由动态链接库造成的,可能跟用户本身设备系统版本和webview版本有关,系统库导致的crash也没有堆栈信息,因此这些问题很难定位原因,比如libc.so导致的crash。还有RN组件本身导致的crash,这些问题都是RN稳定性不如原生的因素之一。
性能优化是应用开发中常见的话题,RN应用的优化需要从JS和原生端同时入手。
我们的项目中使用了Firebase crashlytics来统计分析crash log,从Firebase console可以看到,JS端的exception都会通过RN原生代码抛出,Android中通过ExceptionsManagerModule中的reportException抛出异常信息,iOS则通过RCTAsset中的RCTFormatError抛出异常。JS端的exception一般也会有堆栈信息,可以在js bundle中去查找相关代码定位exception。
Native的crash则分别按照Android和iOS平台的方式去定位,比如Android上传native debug symbol到Google play console,iOS上传dSYM文件到Firebase或相应的统计分析平台,将符号化的日志文件转化成更加清晰的堆栈信息,便于我们分析定位问题。
在实践中我发现很多JS端exception都是代码不规范导致的,轻则导致app白屏重则crash,比如从Object取值的时候Object可能是空的,不存在key value。类似这样的情况一定要谨慎处理,这里建议使用loadash的get函数取值,在取值为undefined的情况,还可以设置默认值。
import _ from "loadash";
const obj = {"key1": "1", "key2": "2"};
const a = _.get(obj, "key1.key2.key3", "");
if (a.length > 0) {
// do something
}
本例中在路径“key1.key2.key3”下都取不到值,a就会是undefined,这时候如果不赋予一个空字符串作为默认值,那么在if判断时就会抛出异常,因为undefined没有length这个属性。在我们平常写代码过程中有很多类似这样的细节需要注意。
官方文档说完善地使用这个函数可以避免重新渲染那些实际没有变化的子组件所带来的额外开销。但是在实际开发中,我们所面临的情况可能比官方给出的例子要复杂得多,实际的业务逻辑、状态变化远远不是一两个变量能cover的。对于这个函数的使用,在不影响系统功能的前提下,可以尽量去用它控制组件的重复渲染,但不要指望它能帮我们handle复杂的业务场景下的页面render规则。
这里贴上很久之前写的一点优化方案,可能部分已经不太适用了。其中防止navigator重复跳转的问题,处理方式并不是好的选择。这里以我目前项目为例,由于使用的是react-navigation,为了防止用户操作过快多次点击导致多次重复跳转同一页面,我们在页面跳转之前会判断下一个页面的routeName,传递的参数等是否与当前stack navigator中存在的页面相同,如果全部相同第二次之后就不再跳转页面。示例代码如下(由于react-navigation版本不同使用API可能略有差异):
export const navigateOnce = (getStateForAction: any) => (action: any, lastState: any) => {
const { type, routeName, params } = action;
return lastState &&
type === NavigationActions.NAVIGATE &&
routeName === lastState.routes.routeName &&
JSON.stringify(params) === JSON.stringify(lastState.routes.params)
? null
: getStateForAction(action, lastState);
};
CustomStackNavigator.router.getStateForAction =
navigateOnce(CustomStackNavigator.router.getStateForAction);
对于一些简单的功能,能自己动手实现的尽量自己写。这里不是提倡重复造轮子,而是引入过多第三方库可能会增加维护的工作量,毕竟不是你自己写的代码,一旦出了bug要么寄希望于他人修复、要么自己来改,而且随着版本迭代,可能这个库已经无法满足当前的功能需求了。一般来说大厂的SDK质量还是有保证的,小厂的或者个人开发者的就不好说了,引入太多第三方SDK也可能对app稳定性造成影响。
开发过程中我们经常需要debug,RN会在本地启动一个package server运行在8081端口,对于iOS来说package server通过websoket与RN建立连接,Android由于通过adb reverse将package server端口映射到Android系统,所以即使断网也能保持package server和app的连接。因此通常需要断网调试时我都是把电脑网络断开,在模拟器上来debug。使用真机debug offline模式会比较麻烦,Android还好,iOS真机一旦断网就无法连接到package server了。如果app某些功能需要断网也能使用的场景,在offline调试时使用模拟器或者Android真机会比较方便一点。
webp其实不属于RN的范畴,它是Google的一种图片格式,使用webp格式图片替代png或jpg格式文件,能够减少图片文件大小,减小应用包的体积。如何转换webp图片可以看google官方文档。像Android项目中的大尺寸图片如splash启动页就可以转换成webp格式,可以大幅减小图片所占空间。
RN中的Image组件加载网络图片比较缓慢,缓存机制不完善,对于大图的显示比较耗时,性能也比较差。这里推荐使用react-native-fast-image,其iOS端基于SDWebImage,Android使用Glide来加载图片,有比较完善的缓存机制,能够快速加载并显示图片。对于图片较多的页面,使用fast image组件能够提高图片渲染速度。
这里我们打debug包的目的只是为了测试,仅供参考。在debug模式下想要不依赖package server让打出的debug包独立运行,需要先将js bundle打出来。可以使用如下命令,以Android为例:
npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output
android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
指定output路径和assets图片资源路径,可以将android bundle文件和图片资源输出到工程目录下,再通过./gradlew assembleDebug打包成debug版本的apk。iOS与此类似,只需要生成js bundle文件和导出assets图片资源,在Xcode——>Build Phases——>Compile Sources添加js bundle和assets的引用,就可以直接通过Xcode进行build。
npx react-native bundle --entry-file index.js --platform ios --dev false --bundle-output
ios/main.jsbundle --assets-dest ios
为了build方便,可以将脚本写到package.json的scripts中,取个别名如ios-bundle,之后可以直接使用npm run ios-bundle进行打包。
禁用字体缩放效果
手机系统调节字体大小后,app中的文本字体大小也会随之变化,尤其在Android上影响非常明显。本来显示效果满分,调整字体大小后UI瞬间错乱。在RN中我们可以通过在app启动时禁用Text和TextInput组件的font scaling来实现,例如:
(Text as any).defaultProps = { ...((Text as any).defaultProps || {}), allowFontScaling: false };
(TextInput as any).defaultProps = { ...((TextInput as any).defaultProps || {}), allowFontScaling: false };
强制使用LTR
有些语言如阿拉伯语、希伯来语是从右往左排列的,当Android手机语言切换到阿拉伯语时,app如果不做任何限制,UI会默认从右向左显示。可以通过如下方案强制LTR(left to right)显示。
在AndroidManifest文件中给application设置
android:supportsRtl="false"
对于一些组件仍然支持RTL样式的,需要在styles.xml中添加layoutDirection,使UI样式为LTR
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:layoutDirection">ltr</item>
在Android Application的onCreate方法中调用RN的I18nUtil,禁用RTL
I18nUtil.getInstance().allowRTL(getApplicationContext(), false);
在debug模式下,有时会遇到chrome有缓存的情况,无论怎么刷新模拟器,chrome dev tools中都无法显示最新代码。此时可以尝试清除浏览器缓存,关闭当前package server并重启。
在语言选择上,为什么要用typescript而不是javascript?因为typescript有类型定义,有类、接口、模块的概念,可以说它是建立在JavaScript的基础上的强类型语言,对于项目开发而言,我们希望每个类每个对象都有比较确定的类型,在编码阶段就能对数据类型进行明确的限定,杜绝错误的数据类型,而不是等到项目编译或者运行阶段才去发现错误,这是JS无法带给我们的。
对于RN端,我们仍然使用常用的Jest框架,这一点与React别无二致。 iOS和Android原生端,仍然使用各自平台的测试框架,iOS用XCTest.framework,Android通常使用JUnit、AndroidJUnitRunner和Mockito。
RN作为移动端跨平台开发框架来说,优缺点十分明显。优点是上手比较简单,开发者生态比较活跃,社区资源也比较丰富,缺点是性能稳定性与原生平台还是存在一定差距的,尤其是对功能复杂、与原生交互较多的应用可能并不适用RN开发。虽然近年来使用RN开发的热度貌似有所降低,尤其是以Airbnb为首的一些公司放弃了RN,并且Flutter这样跨平台框架的崛起,导致网上出现很多“RN已经凉了”的声音。但是时至今日,RN仍然还在很多项目中得到广泛应用,Facebook仍然还在持续维护,开发者生态依然生机勃勃,可以说RN的生态是移动端跨平台开发框架中最好的也不为过,说凉凉还为时过早。
我个人认为RN依然是有竞争力的,至于要不要用RN在技术选型阶段还是要多考虑考虑,怎么用、用不用得好在开发阶段就需要多研究,在实践过程中不断优化改进。最后,欢迎大家一起探讨,有好的实践可以互相交流。
参考文章
文/Thoughtworks朱浩
原文链接:
https://insights.thoughtworks.cn/react-native-practice/
更多精彩洞见,请关注微信公众号Thoughtworks洞见。
本站部分资源搜集整理于互联网或者网友提供,仅供学习与交流使用,如果不小心侵犯到你的权益,请及时联系我们删除该资源。