We're sunsetting PodQuest on 2025-07-28. Thank you for your support!
Export Podcast Subscriptions
People
D
Dan Gardner
Topics
Dan Gardner: 我是一位软件开发者,也是一位偶然的企业家。2008年,为了学习PHP/MySQL,我开发了一个名为RunPee的应用,它能告诉你电影中最佳的如厕时间,避免错过精彩片段。这个应用的成功出乎我的意料,它成为我主要的收入来源,并持续支持我的家庭超过13年。2020年,我和妻子使用Flutter重构了RunPee应用。我们都非常喜欢Flutter框架,并在自由职业工作中继续使用它。RunPee的成功并非一蹴而就,它经历了从网页应用到移动应用的转变,也经历了用户行为与预期不符的挑战。我们通过持续改进,积极回应用户反馈,并找到产品与市场的契合点,最终取得了成功。RunPee的成功秘诀在于其有趣的故事性和易于分享性,以及我们对用户反馈的高度重视。我们简化了用户反馈流程,方便用户报告错误和提供建议,并根据用户需求添加了新的功能,例如IMDB和烂番茄链接以及‘额外内容’功能。RunPee采用免费增值模式,用户可以选择观看广告或订阅付费版本。在后端方面,我们仍然使用PHP和MySQL,并对API进行版本控制,以避免更新时影响到旧版本应用的用户。未来,我计划尝试使用Firebase和AWS等不同的后端技术。 Hillel Korn: 作为访谈者,我没有表达具体的观点,而是引导Dan Gardner分享了他的开发经验和RunPee应用的成功故事。我主要关注了RunPee应用的技术选型、状态管理方案、后端架构以及用户反馈等方面。 supporting_evidences Dan Gardner: 'It just took off, like surprised me as much as anybody else. And that's been my primary source of income ever since.' Dan Gardner: 'So this is 2008, August of 2008. I built, it was literally a web application built with Adobe Flex.' Dan Gardner: 'The data needs to be so precise. You know, we need to know exactly when and exactly what happens. So we actually have to go watch all of the movies ourselves.' Dan Gardner: 'And I thought, you know, I'm going to give this another chance. And I started going to see movies pretty frequently to have like a, you know, a full database of recent movies in there.' Dan Gardner: 'It sounds like it was a journey toward finding product market fit, which is really interesting and a good lesson for many people.' Dan Gardner: 'I think that two keys to RunP's success are, A, that it's a fun story to tell.' Dan Gardner: 'is making it very easy to interface with our users. So we share our Twitter account and we've got a Facebook account that somebody else manages because I got off of that.' Dan Gardner: 'So our pay model is you can use the app for free forever and just view advertisements.' Dan Gardner: 'Well, yeah, I hadn't been doing any freelance work throughout probably 2013 until 2020. I was living off of entirely the RunP app.' Dan Gardner: 'Oh my God. It's just like, I see pictures like screenshots of the old app and I'm like, Oh, how did I ever let it look like that? Like it looks so much better.' Dan Gardner: 'when it was time to choose a new framework. So first, it was definitely going to be cross-platform because I'm not going to build two apps.' Dan Gardner: 'Coming from Flex, I had a system that I'd already built myself for state management.' Dan Gardner: 'Oh, wow. Still PHP MySQL running on a Apache server.' Dan Gardner: 'So with every version, with every update of the run P app, it gets its own API and it may be identical to the previous one, but like I, you know, there's a path on the server to it.'

Deep Dive

Shownotes Transcript

Dan Gardner:软件开发者兼意外的企业家。早在2008年,他需要学习PHP/MySQL,因此他构建了一个名为RunPee.com的网络应用程序。(它会告诉你电影中最佳的去洗手间时间,而不会错过最佳场景。)该网站获得了国际上的成功,并发展成为一个移动应用程序和业务,在过去的13多年里一直支持着他和他的家人。2020年,他和妻子使用Flutter从头开始重建了RunPee应用程序。他们都喜欢这个框架,并继续在今天的自由职业工作中使用它。

https://play.google.com/console/about/weareplay-us/#storyCards-NC

https://flex.apache.org

https://laravel.com

https://fluttervikings.com</context> <raw_text>0 嗨,感谢您的收听。这是It's So Widget的Flutter播客。我的名字是Hillel Korn。在每一集中,你都有机会与Flutter社区的另一位优秀成员交谈。在本集中,我们非常幸运地与Dan交谈。欢迎。嗨,感谢邀请我。我真的很感激。感谢你参加播客。那么,首先,你想分享一些关于你的背景信息吗?是的。好吧,我想我在这里的主要原因是谈论我构建的一个名为RunPee的应用程序。

这是一个应用程序,它会告诉你电影中最佳的去洗手间时间,这样你就不会错过最佳场景。我想,这就是我的成名之作。我是一个哲学和历史专业的学生,花很少的时间阅读哲学,而花大量的时间在90年代学习JavaScript和CSS。这逐渐演变成……

有点像在2000年代初期为公司开发网站之类的工作。然后我在微软Xbox担任Flash原型设计师。作为微软的Flash开发者,那段时光真的很有趣。这样的人不多。然后我辞去了微软的工作,成为一名自由职业开发者,然后

决定,我需要一些东西来增强我的作品集,我需要学习MySQL和一些PHP,我从未构建过数据驱动的应用程序,所以我想,你知道,我有一个RunPee的想法,它很愚蠢,但我想我会构建它,然后……

它突然火了,这让我和其他人一样惊讶。从那以后,它就成为我主要的收入来源。这是一个很棒的故事。真的很酷。我很好奇。所以,当你第一次发布这个应用程序时,它是立即获得成功,还是有一个建立用户群的过程?是也不是。这是2008年8月。我构建的,它实际上是一个使用Adobe Flex构建的网络应用程序。

我的意思是,就像我说的,2008年,并没有那么多……

移动应用程序。而且,呃,我构建了它,并参加了那一年在圣何塞举行的Flex 360 Flex大会。他们让我上台谈论它。每个人都像,“哦,我的上帝,太棒了”。然后是沉默,你知道的,我回家后,每天只有两个人使用这个网站。而且,呃,

它最初有点像维基百科,用户可以提交他们认为电影中最佳的去洗手间时间。这是我最初的想法,我认为这就是它的运作方式。许多人,尤其是开发者,当我解释这个应用程序的工作原理时,他们认为它是用户生成的内容。但事实证明,

数据需要非常精确。我们需要准确地知道何时以及发生了什么。所以我们实际上必须自己去看所有的电影。所以,这有好有坏。但是,是的,从2008年到2009年春天,它一直不温不火。

我心想,我会再给它一次机会。我开始频繁去看电影,以便在其中拥有一个完整的最新电影数据库。就在这时,2009年的《星际迷航》上映了,社交媒体也刚刚开始发展。我为那部电影添加了去洗手间时间,

当时我还添加了一个反向去洗手间时间。许多看过这部电影的人,你本能地会感觉到电影中什么时候可以去洗手间。当柯克降落在那个冰冻星球上时,人们会说,“哦,我想这是个好时机”。所以他们跑去洗手间。

然后他们回来,柯克正在和原版史波克说话。他们说,“等等,发生了什么?怎么回事?”所以他们完全迷失了方向。就像,“嘿,有一个应用程序可以告诉你,不要在这个时候去洗手间”。这引发了很多讨论。我尽快构建了一个移动应用程序,并在2009年7月4日发布。

从那时起,它就开始流行了。非常酷。听起来像是找到产品市场契合点的旅程,这非常有趣,对许多人来说也是一个很好的教训。我做过许多自己动手的小项目,当我回顾过去时,我觉得我不得不更加努力,并且不能过早放弃。也许我会更成功。有趣的是,你对用户行为会有某种期望,一旦你发布产品并查看人们是否使用该应用程序,它并不总是与现实相符。对。是的,这是一个关键方面。

找到一些可以成为你的布道者的用户,以及何时放弃并说,“好吧,是的,这永远不会获得关注,或者这只是时间问题?”没有人能回答这个问题。有很多东西成功了,我认为它们之所以成功,仅仅是因为它们在恰当的时间流行起来。

很多东西都失败了,但它们本可以在合适的环境中取得成功。你永远不知道。

我认为RunPee的优点在于你拥有垄断地位,这很棒,对吧?在创业市场领域,这就是你想要的。如果人们想知道什么时候去洗手间,你就是那个人。来你的应用程序吧。是的。实际上,在2012年或2013年左右出现了一个竞争对手?哦,不。他们是否复制了你作为模仿者?是的,他们完全复制了。它实际上被称为P-Run而不是Run-Pee。直到……

有人在支持部门联系我,他们说,“哦,应用程序没有更新,电影不对,所有这些乱七八糟的事情”。他们向我描述它,就像,“这不可能”。

我说,“你能给我发个截图吗?那甚至不是我的应用程序”。我现在正在为别人的应用程序提供技术支持。我认为他们意识到这比他们想象的要费力得多。我认为他们会说模仿是最高的赞美形式。没错。是的。所以他们消失了。我时不时地会有点担心,IMDB可能会完全像,“呸”。

我们会投入10万美元来解决这个问题,并将其彻底解决,每个人都会使用我们的版本。他们从未这样做过。我们实际上……我们的RunPee数据已获得AMC影院的许可。因此,如果你使用AMC影院应用程序,你也可以在那里找到去洗手间时间。有RunPee的标志,他们的版本非常……

呃,笨拙,与应用程序相比,但它提供了基本功能,这非常有趣,是的,我认为这是许多创业开发者最害怕的事情之一,你想要取得一定的成功,但当你过于成功时,它就会成为一个问题,然后你就会成为一个更大的目标,是的,当然,你知道,我不知道该说什么,这每个人都会面临的事情,所以我们都在同一条船上,呃……

做得更好。我认为RunPee成功的两个关键是,A,这是一个有趣的故事。所以我们的用户总是告诉我,就像我与我的整个家庭分享这个,我与工作中的人分享这个,完全没有提示。我相信每个收听节目的观众都能想象得到,即使你没有使用这个应用程序,

如果你乐意与一群朋友谈论电影,你会说,“哦,我的上帝,我必须告诉你这个应用程序,因为它让你成为关注的中心”。分享有趣、有用的信息感觉很好。而且它并不真正具有争议性。就像,

没有人会说,“哦,我完全不同意。你知道,我站在另一边”。这在政治上行不通,或者其他什么。就像,那不会发生。所以,是的,这只是一个有趣的分享。不仅仅是我们的用户,CNN也在其娱乐网站的首页上分享了RunPee,并在《复仇者联盟4:终局之战》上映时导致服务器崩溃。所以,是的,

耶,但是糟糕。对。我喜欢电影。我是一个超级影迷。我喜欢长电影。好吧,很好。你就在我们的目标人群中。对。

让与我们的用户互动变得非常容易。所以我们分享我们的Twitter账户,我们还有一个由其他人管理的Facebook账户,因为我已经离开了。

但是,就像我回复Twitter上的所有内容一样。如果你提到RunPee,你知道,我至少会点赞它,并向你展示,是的,我听到了你,或者这是一个问题。我总是会回复。我回复我们收到的每一封电子邮件。我还让用户可以直接从应用程序中向我发送电子邮件,这非常非常容易。

它包含了他们在应用程序中的位置的上下文。所以一件非常常见的事情是,你知道,我们在概要中犯了错误。也许是我们使用了错误的角色,说了这样那样的话,或者可能只是一个错字。就在屏幕上,当你阅读去洗手间时间的概要时,

我想我应该详细介绍一下这个应用程序的工作原理,但是有这些去洗手间时间,它会告诉你,电影的第43分钟,当莎拉说“滚出我的房子”时,你可以去洗手间,你知道,这就是你的提示。如果你去洗手间,那么你可以,

点击查看概要,并阅读你在离开时发生的事情的简短摘要。然后就在屏幕底部,它会说,“嘿,你有没有注意到什么问题?有什么反馈吗?”他们可以说,“某某没有这么说”。然后

很容易联系我。它已经包含了他们正在观看的电影、他们正在使用的去洗手间时间。所以我尽量让用户提供反馈变得尽可能简单,你知道,这帮助我们获得了满足他们需求的新功能。所以,你知道,我们添加了到IMDB和烂番茄的链接,因为人们说,“嘿,你知道,这会很方便”。而且

这是一件很容易添加的事情。我们添加了“额外内容”,因为用户说,“嘿,你能让我们知道片尾有没有额外内容吗?”我的意思是,你已经在看电影了。所以我们添加了这个功能,而且它非常受欢迎。很多人只是为了查看电影中是否有额外内容而使用这个应用程序。还有其他服务提供此功能,但它们是众包的。

我们做得非常好,例如片尾有9分钟长,有两个额外场景。其中一个在大约2分半钟后,还有一个额外场景。然后在片尾之后,可能还有一个。而其他服务只是简单地说是或否。我们提供了所有这些。额外内容没有付费墙,也没有广告。你可以,

如果你使用RunPee应用程序来查看额外内容,你将永远不会看到广告,你也不需要花钱。这是一个很棒的功能。我仅仅是为了这个功能就会使用这个应用程序。没有什么比坐在那里看9分钟的片尾然后什么也没有更糟糕的了。对,对。我们之所以这样做,是因为有些人确实像我说的那样只为了这个功能而使用它。我们没有从他们那里赚钱,但他们确实拥有这个应用程序,并且可以提醒他们与其他人分享。所以

所以我们的付费模式是你可以永远免费使用这个应用程序,并且只观看广告。你还可以选择何时观看广告,因为如果你正在看电影的一半,然后,“哦,我需要去洗手间”。

你打开应用程序,然后你的脸上出现一个视频。就像,“哦,糟糕”。你知道吗?所以我们让你选择何时观看广告。或者,如果你看了很多电影,并且想支持我们,并且不想处理广告,那么你可以每月订阅1美元。这并非适合所有人,但它作为一个选项存在。

不错。这很有趣。所以在这个公司的故事中,你已经开发了一个,使用Flex来构建移动应用程序。然后很明显,我们在这里是因为我们切换到了Flutter。所以我很想知道你的思考过程,包括,你知道,是什么促使你切换,以及你为什么选择Flutter?

好吧,是的,从2013年到2020年,我几乎没有做过任何自由职业工作。我一直靠RunPee应用程序生活。我有点渴望重返这个领域。而且Flex和Air不再有需求了。

此外,我还担心Air的未来,因为Harman已经接管了。它将得到多好的支持?这个应用程序需要改头换面。对我来说,当时我是一个开发者,而不是设计师,它看起来还可以。现在它已经用Flutter重建了,

哦,我的上帝。就像,我看到旧应用程序的截图,我说,“哦,我怎么能让它看起来像那样?”它看起来好多了。然后很明显,它的性能要好得多。更重要的是,它具有未来性。我觉得很有信心,你知道,我们可以至少使用Flutter十年,而不用担心,你知道,我们是否应该采用新的东西,适应新的东西?

在选择新框架的时候。首先,它肯定是要跨平台的,因为我不会构建两个应用程序。我对此从未感兴趣。此外,我不会编写JavaScript,因为我不喜欢JavaScript。我喜欢类型化语言。我不喜欢HTML、CSS的世界。你知道,每次我必须去修改我的

RunPee.com的WordPress博客,然后进入CSS,我都会说,“哦,这是一个噩梦”。而且,你知道,向那些这方面的专家致敬。脱帽致敬,但这并不是我想涉足的东西。幸运的是,Flutter刚刚超过了1.0版本。我的妻子实际上是第一个发现它的,

她说,“这看起来非常有趣”。我们对此进行了研究,并在Udemy上参加了Angela Yu的课程,她是一位很棒的讲师。然后我们重建了这个应用程序。从那以后,我一直使用Flutter做一些自由职业工作,以增加一些额外的收入。

酷。自从发布以来,用户的反应如何?很明显,你正在切换应用程序。我认为你更新了一个版本,他们从旧应用程序切换到新应用程序。是否有积极的回应或任何担忧?是的,是的。压倒性地积极。就像我说的,它看起来好多了。它的功能仍然与旧应用程序相同。导航没有根本性的改变。

所以这对用户来说很方便。我想我遇到的一个问题是,我非常幸运,我可能至少提前一年就预料到了这一点,那就是从数据库中获取数据用于本地存储。现在,当你拥有它时,你会认为,“哦,你在同一个沙箱中”。所以你只需要打开那些MySQL Lite数据库

数据库等等。一切都很酷。但事实并非如此。我所做的是,我在文本文件中存储了用户的ID号。这很容易找到。它位于沙箱的根目录。所以当我迁移到Flutter时,我只需要找到那个文件。我知道用户的ID号。根据他们的ID号,我可以自动登录他们

我不必像试图,你知道,弄清楚如何使用旧数据或任何类似的东西,可以无缝地迁移。这花了我很长时间来解决这个问题。呃,但是,是的,这确实使绝大多数用户的过渡变得非常顺利。呃,你知道,他们有一天打开应用程序,这也发生在大流行期间。呃,

所以每天更新的人很少。实际上,我现在仍然有人刚刚获得新版本,他们给我发邮件,说,“哦,我的上帝,我喜欢这个”。这什么时候发生的?我想现在是两年前了。让我们谈谈应用程序本身。我觉得在这个播客的每一集中,我都谈到了状态管理。那么,你使用了哪个包,或者这个应用程序是如何构建的?好的。所以,

从Flex而来,我已经为自己构建了一个状态管理系统。当我学习Flutter时,我也这么做了。我真的很喜欢它对状态管理是不可知的。它不会强加于你。所以我尝试了Block和GetX。

还有其他几个,你知道,我不记得它们的名字了,但是,你知道,如果你去阅读,如果你搜索“Flutter状态管理前五名”,每个人都会给你基本上前五名。我试用了所有这些,但都不喜欢。除了只使用setState和change_notifier的默认方法之外,你

它很简单。当我需要查找错误时,我可以跟踪代码的执行。我不明白为什么特别是Block,因为我不得不在其他项目中使用它。

我只是不明白为什么有人会使用它,但萝卜青菜各有所爱,对吧?是的,而且我认为所有不同的选项,我认为我们许多开发者在脑海中对代码的建模方式不同。例如,有些人喜欢事件结构,它是一个事件循环,用户通过点击和点击来参与这个循环,他们正在触发事件。从这个角度来看,Block与使用流和事件流的结合是有意义的。

但是对于更简单的应用程序或其他类型的应用程序,其他模式肯定更有意义。是的,我不喜欢在小部件之间传递数据,除非,你知道,像从一个到另一个,我可以接受。你知道,很明显,你构建一个小部件,它需要与它的父级通信,这很好。当你必须传递给多个小部件,并且你拥有树状结构时,它感觉就像现在……

每个小部件都像被锁定在其所在的位置一样。修剪它们有点困难。也许这只是我没有深入到使用Block的程度,但我希望我的视图知道数据,但数据不知道视图,你知道吗?例如,如果任何类似用户数据发生更改,

那么我可以发送一个通知器。嘿,关于用户的一些内容发生了更改。如果我碰巧在一个可能需要反映此更改的屏幕上,嘿,让我们再次设置状态并获取新数据。如果我不在一个包含任何用户数据的屏幕上,我不关心后台的用户数据是否发生了更改。所以这看起来是最少管道连接的方式,我想,

对我来说。是的。不,这对我来说很有意义。我认为我发现Flutter的一个特点是,如果你深入到性能级别,setState的性能可能不如其他选项。但是,Flutter通常性能非常好,以至于在更简单的应用程序中,你损失的性能你并不一定会注意到。

我认为我发现我们的应用程序是,一旦我们切换到Flutter Web,这些性能问题就会浮出水面,因为它们变得更加清晰,性能受到更多限制的地方。但在移动设备上,特别是,我发现大多数Flutter应用程序开箱即用就非常快,无论它们是如何构建的。哦,当然。是的,你真的必须搞砸才能,才能,才能获得移动应用程序的性能。是的。

就像,“哦,等等,我是否在构建中调用了那个循环?哦,糟糕。这就是为什么……就像,好吧,不要那样做。对于许多需要……的小部件,我的过程是,例如,我使用一个变量小部件作为主体,例如对于脚手架。并说它将在那里加载数据。所以在这个时候,我甚至不需要更改通知器,因为……

我将其设置为圆形进度指示器。所以这将是脚手架的主体或包含它的一个小部件。它加载并说,“嘿,默认情况下你会看到一个微调器”。然后在initState中,你调用一个异步方法。它说,“嘿,去获取这个数据”。当这个数据返回时,如果成功,

然后显示包含我们刚刚获取的数据的视图。如果失败,则显示错误。然后设置状态。所以,你知道,在这个整个场景中,你只设置一次状态。所以,是的,你知道,如果你由于某种原因,正在左右广播事件并反复设置状态,你可能会遇到麻烦。但我认为此时你需要查看,例如,

我正在用我的数据做什么?我的数据为什么变化如此频繁?伙计,让我告诉你,你也可以用Block做到这一点。因为我最近参与的这个应用程序,我们必须修复其中的一些问题。所以我认为我对Block的一个问题是,有很多方法可以真正做错。我想这可能是大多数状态管理的共同点。就像,

如果你没有正确操作,你很容易就会遇到Block的可怕性能问题。

这是一个有趣的观点。我发现当我第一次学习设计模式时也是如此。每次我学习一个新的设计模式时,我都会非常兴奋。我一直渴望使用它并应用它。我发现如果我只是编写简单的代码,它通常运行得很好。如果我尝试应用错误的模式,那将是一场灾难。这将是一段非常糟糕的代码。显然,如果你找到了合适的模式,那是最好的情况。但是当你选择错误然后继续使用它时,这可能会非常困难。因为同样,你可能会朝着应用程序真正需要的方向过度工程。

是的。并不理想。我很好奇你使用什么作为后端,以及你如何将前端与后端通信?哦,哇。仍然是运行在Apache服务器上的PHP MySQL。我实际上正在使用WP Engine。那是WordPress。它是针对WordPress优化的。这几乎是他们所做的全部工作。我将其用于runp.com。然后我有runp.net。

是用于应用程序的API。所以将来,所以这是我做过的最愚蠢的事情之一。就像,我只想回到我2018年的自己。就像,“不要将API放在与博客相同的域名上”,你知道吗?所以当CNN发布了,

呃,关于RunPee的所有这些内容,所有这些人都来到runp.com。它不堪重负。而且,你知道,WordPress是一个相当大的负担。呃,它使服务器不堪重负,你知道,它也使,呃,

应用程序API也无法连接。应用程序的RunPee API非常非常小。它只发送非常非常少的数据。所以它运行在它自己的服务器上。它自己很开心。几乎没有什么可能出错。

话虽如此,这个月,或者下个月,我正在构建一个应用程序,我将使用Firebase和AWS以及其他一些,因为我从未需要使用其他后端。

而且我觉得人们都在谈论所有这些其他选项,GraphQL。就像,“好吧,你知道,我应该构建一些示例应用程序,并了解它们擅长什么以及它们不擅长什么”。因为我现在在我的工具箱里只有一个工具,那就是PHP和MySQL,它可以工作,但可能还有更好的解决方案。所以我将花一个月的时间来尝试不同的后端来完成同一个项目,看看,你知道,什么对每个人来说最有效。

不同的东西。- 酷,祝你好运。我很想知道结果如何。- 你最喜欢的后端是什么?- 我实际上也使用MySQL和PHP。Laravel是谁?你熟悉Laravel框架吗?- 我不在后端使用框架。我只是-- - 它是一个PHP框架,用于PHP。它与Ruby on Rails非常相似。它有点像PHP的Ruby on Rails。然后我们创建一个非常简单的REST API,它可以工作。好处、坏处、优缺点。它非常快。

它非常便宜。这两个都非常好。缺点是,我认为它需要相当多的维护,以及可以维护它的人。我很幸运有一个在这个领域很精通的合作伙伴来帮助我。但是如果我只是独自在一个应用程序上工作,我很有可能会使用Firebase,仅仅是因为安心。你有一个始终可用、始终运行、不需要更新的后端。没错。我想我在开发RunPee应用程序中最大的收获是……

对后端进行版本控制。因此,对于 RunPee 应用的每个版本、每次更新,它都会拥有自己的 API,它可能与之前的 API 相同,但是,你知道,服务器上有一条通向它的路径。而且,你知道,我有 6.1 或 6.0、6.1、6.2、6.3 等等版本。所以,任何时候我想更改 API,我都可以进去将其清除并重构整个内容。我不必担心,

担心会搞砸那些尚未更新应用的用户。我正在做一个已经发布的客户项目,他们没有对 API 进行版本控制,这带来了无尽的麻烦。就像,好吧,我们不能那样做,因为那会把这些人搞砸。而我想,好吧,我们该如何修复任何东西?还有什么想补充的吗?哦,天哪。是的。

我真的很兴奋 Flutter。希望新冠疫情正在消退。我很想参加一些 Flutter 大会,结识一些其他的 Flutter 开发者。我认为这是我非常怀念 Flex 的东西之一。我仍然与许多我以前的 Flex 同事(包括男性和女性)保持着很好的友谊。

你知道,在,我认为,实际上是 360 Flex 大会开始于