详情

全站展示位

Flutter中嵌入Native组件 |

Flutter官方提供的控件AndroidView、UiKitView就是一种比较优雅的解决方案了。这里做了一个简单的嵌入TextView的demo(使用这种方式会增加性能上的开销,应该尽量避免使用) 使用方式 native端 跟MethodChannel的使用方法类似,在native侧,我们实现一个PlatformViewFactory(iOS是FlutterPlatformViewFactory),在create方法中,使用平台方法创建View返回。 override fun create(context: Context?, i: Int, any: Any?): PlatformView { return object : PlatformView { override fun getView(): View { val text = TextView(context) text.layoutParams = ViewGroup.LayoutParams(SizeUtils.dp2px(200f), SizeUtils.dp2px(200f)) text.apply { setText("Android View") setTextColor(Color.BLUE) setBackgroundColor(Color.RED) } return text } override fun dispose() { } } } func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?。。。

推荐

琥珀之月,空谷之兰,皆是孤芳,既是孤芳,但求自赏便罢!

30字的完美简历[转载] |

这个世界上,总有很多人很自以为是地以为若是他们做不到的事情,别人做到了,必定不是什么光彩的正道,必定不是靠自己的实力。包括我。 曾经看到托福GMAT拿满分的人,就会想着:“怎么可能!这个人肯定是小时候在国外生活过吧!” 看到保养地特别好的中年女人,就会撇嘴:“肯定是花重金打玻尿酸啊这针那针啊!” 看到年纪貌美的女孩开着豪车经过,就会想着:“肯定是二奶呀!” 看到年纪轻轻上了富豪榜的青年才俊,就会揣测:“肯定是家族企业啊!” 看到年少成名靠参加选秀红遍大江南北的歌手明星,就会怀疑人家:“估计是被潜规则了。” …… 这样的例子几乎每天都发生着,我也曾一度全然不觉自己在这样的渊里越堕越深。 直到大四有一次去参加一个牛逼公司的面试,面试通知邮件里最后有一条是:请携带不超过30字的Personal Statement(简称PS,个人陈述)。 我一看,疯了吧?30字?!我挨个把自己工作实习过的公司名字和读过书的学校名字列一遍都不止30个字了啊?!我想了想,绝对不可能!应该是他们漏写了个0吧?于是便也不去多想了。 等到面试那天,我带了份自认为已经是非常简洁的PS过去,一路上都觉得真是憋屈啊,很多东西没写进去呢实在没有发挥我洋洋洒洒的特点,都没充分展示我的闪光点呢!但是没办法还是尽量符合这个公司简洁精准的办事风格来吧。 到了公司,我递交上我的PS后,三个面试官不约而同皱起了眉头,一个头发花白的外国男人问我:“你这个字数超过30字了,起码得有400字吧,为什么不按我们的要求做?” 我愣了一下,什么?真的是30字?不是逗我玩? 我有点怀疑地说:“30字?30字写一篇PS根本是不可能做到的呀!这字数也太少了吧!” 一个女面试官很凌厉的口气说:“不可能?不可能的事情我们怎么会要求你做?”她说着把一叠PS亮在我面前,“他们都可能,为什么只有你不可能?” 我刷地一下脸就红了,支吾着说不出话。这是我唯一一次期待着面试官赶紧说:“好了可以了,请你出去吧。” 但是试场里出现里几秒钟的沉默,这几秒钟对我来说,竟然跟失眠的夜晚一样难熬。 那花白头发面试官又开口了:“你觉得这个世界上不可能的事情,是因为你没有试着去做。” 我犹豫了一下说:“谢谢您。我知道我的问题出在哪里了。不知道是否方便让我看一眼其他人的PS,我想知道自己的差距有多大。” 他们几个互相望了一下,点头示意后将一沓PS递给我。 我在拿过来的一瞬间已经被最上面的一份震惊到了。 那整张纸上画了一个应该是以面试者自己为原型的卡通人物,最上面是他的名字,然后是一个巨大的脑袋,脑袋顶部是开放的,用一大片电脑芯片画成了原始森林的样子,旁边写着“computerized mind”,左手拿着画板,写着“Photoshop Skiller ”,右手举着一叠报告,写着“Reportexpert”, 中间的领带处别着个话筒,上面写着“Good Presenter”,心脏的位置画了一颗奇形怪状的心,写着“Creative heart”,脚踩锃亮的皮鞋,穿着毫无褶皱的西裤,旁边写着“Detail-cared”…… 我一边看,一边手心出汗。 这样一份不超过20个单词的PS,我在看完四年后的今天还能够一字不差地回想起来,并且画面栩栩如生,你可以想象它当时带给我的震惊,以及给面试官们带来的印象有多深刻。 接下来的一沓PS里,有画一个大转盘,写出自己的几个特质的;有在一条竖直的时间轴上写了自己做成的几件大事的;还有剪切了几幅自己参加过的作品粘上去的…… 总之没有一个是多于30个字的! 但是每一份PS我看完都如同看到了一个活生生的人站在我面前,我知道他的个性如何,特长是什么,有过什么值得称赞的荣誉。 而我那张全是字的白纸,恐怕人家连看都不想看,即使看了,也不会留下任何印象。 我很不好意思地将一摞纸还给面试官,很诚恳地鞠了一躬,“很抱歉浪费了你们的时间,在来这里之前,我总觉得有些事我做不到,就是不可能做的到的。谢谢你们让我知道我的想法有多愚蠢。谢谢。” 我关上身后那扇门的时候,长长地吁了一口气。 回去的一路,都走的很慢。 我不是在难过失掉了这么一个工作机会,而是在难过地回想在过去的十几年光阴里我究竟失掉了多少次机会?让本该存在的可能,成了我嘴里的不可能。 我明白了一个让人很恼火去承认的事实就是: 那些我觉得不可能的事情,其实根本不是不可能,只是我认为不可能而已。 对一个根本不会去思考去想办法的庸人来说,很多事情都会成为不可能! 后来我试着去做一份字数在30字以内的简历,用了四个晚上后,真的也做出来了。 后来我试着再去做另一份简报似的简历,在用了三个晚上后,同样也真的做出来了。 而在之前,我认为简历就该是白纸黑字,从教育背景到工作经验到兴趣爱好,但其实它充满了那么多的可能性! 可是真的该如此理所当然吗? 我们自己不可能做到,真的是因为我们无能,还是我们根本没有尝试去做? 托福考满分的同学,说不定我们没看到的是,人家起早摸黑悬梁刺股每天练口语练到喉咙发炎; 开着豪车的美女,说不定我们没看到的是,姑娘辛苦打拼几年每天工作累得像狗辛苦攒钱; 保养的很好的中年女人,说不定我们没看到的是,她们每天下班后还去健身房睡觉一定不趴着睡,每晚一定做面膜,十几年如一日; 优秀的青年企业家们,说不定我们没看到的是,他们无数个不眠不休的夜晚,付出比我们这些在睡梦中的人多的多的努力; 那些一朝红遍全国的明星,说不定我们没看到的是,人家之前十几年的默默无闻用心苦练基本功…… 我们什么都没看到,就说别人不可能;我们什么都没去尝试,就说这事不可能。 其实,我们觉得不可能做到的事情,别人真的可以做到。对一个根本不敢去做的人来说,一切都是不可能。 想是问题,做是答案,有时候答案就藏在问题后面!

Android Jetpack Compose 超快速上手指南 |

Compose 介绍 Jetpack Compose发布也快有一年的时间了,虽然目前仍是DEV阶段,但是距离可用已经不远了。Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速度(可以参考几乎一模一样的Flutter,开发速度确实很快)。 Jetpack Compose对于没有接触过声明式UI的小伙伴可能会学习曲线有点陡峭,对于已经能熟练开发Flutter应用的小伙白来说几乎没有难度。(Compose就是参考flutter的模式开发的,代码中还可以看到Flutter的相关注释) 这篇文章不回去解释过多的原理与技巧,只要是让你能够快速上手开发项目。 Compose 如何使用 因为目前(2020年09月27日)Compose仍处于开发阶段,所以需要使用最新 Canary 版的 Android Studio 预览版。 可以选择直接创建Empty Compose Activity来创建一个全新的Compose应用,或者可以选手动修改gradle的方式来创建Compose应用 修改Gradle 在模块的build.gradle文件中新增: android { ... kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.4.0' } } dependencies中新增: implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.ui:ui-tooling:$compose_version" 目前最新的Compose版本是1.0.0-alpha03 使用Compose最低的buildTools版本要求为29 使用 @Compose 所有关于构建View的方法都必须添加@Compose的注解才可以。并且@Compose跟协程的Suspend的使用方法比较类似,被@Compose的注解的方法只能在同样被@Comopse注解的方法中才能被调用

解决 golang IDEA中不能debug问题 |

IDEA是2018-01版本,Golang是go-1.12.1,IDEA在Plugins中安裝的Go插件,我在运行go程序時是正常的,但是提示could not launch process: decoding dwarf section info at offset 0x0: too short 解決方案: 1:在终端运行 go get -u github.com/derekparker/delve/cmd/dlv。 2:运行上面的命令之后运行环境中就有dlv了。替换IDEA go 插件中的dlv macOS中的插件地址是:/Users/用户名 /Library/Application Support/IntelliJIdea2018.1/intellij-go/lib/dlv/mac 替换之后就正常了。

心灵鸡汤

被优待的高考

文/蔚新敏

高考被优待,有的加分,有的优先录取,1994年我高考,优待睡竹躺椅。

高考前,邪门了,白天下雨晚上晴天,潮乎乎的热。我家有一个躺椅,竹板做的,躺上去,倍儿凉快,那是我爸的宝椅,平时谁都不能躺。7月6号晚上,我爸说:“明天你高考,今晚上躺椅归你,想躺到几点就几点。”我受宠若惊呀,这“小灶”开得别具一格,可能是我爸表达对我高考重视的唯一途径。

那天晚上,我和衣躺躺椅上看书,我爸把落地扇脑袋调成对着我呼呼吹,我是大暑天下河,凉快透了。

那么一躺就睡着了,一夜都没翻身。

早晨醒来,我的胳膊、脖子、腰、腿都好像坠着沙袋般发沉,各个关节都不活泛了,第一是让躺椅的竹板硌的,第二是电扇吹着了。我也不敢说,就那么去参加考试了。

我的座位在最后一排,我屁股上扎着蒺藜似的,坐不住凳子。腰酸,我就把腰挺得倍儿直溜,直着不舒服了我瘫桌上,过会儿再脖子拉长了腰板挺直了“眺望远方”……总之,人家都低头答题,我摇头晃脑可忙乎了,字都没写多少。

监考的老师走过来,也不问我怎么回事,给我脖子上抹了点风油精,以为我是被蚊子咬了呢。见我还不“老实”,估计是以为我偷看左右同学的答案,也不经过我同意,提溜起我的身体,直接把我的凳子往后拽,桌子往后挪。另外一个老师走过来,身体挡在我前面,恰好头顶一个吊扇,忽闪忽闪转,吹得我更难受。俩老师配合默契,瞅着我,意思是“这下你可凉快了”。我何尝不知道其实是防着我抄袭。那天的考试,我成了药店的抹布,苦透了。

第一天的考试不怎么好。可也不敢跟家里人说啊,吃罢晚饭,我爸说:“你辛苦了,今儿晚上,躺椅还归你,电扇还归你。”我赶紧溜到自己的床上,佯装睡着,待我爸叫我去睡躺椅,我假装睡得死死的,呼噜那个响哦,睡得那个沉哦,怎么叫都叫不醒。那天晚上,真热,我整夜大汗淋漓,第二天,浑身酸疼的感觉没了。

后来我就总结,把高考平常化,别给孩子太特殊的待遇,万一不适应,反而弄巧成拙。

父亲的考前忠告

文/李育蒙

说起高考,我不算成功者。第一年高考失利以后,我背上行囊南下深圳打工,在一家工厂喷油漆。工作了一个多月,父亲打来电话,问我想清楚没有是否复读?差不多同一时间,高三的班主任也打来电话劝我返校复读。因为家里条件不好,我还是非常犹豫。倒是父亲一再坚持要我上学,拗不过父亲,我辞掉了工作还是回学校复读。这其中一个最现实的动力是,班主任电话里和我说,已经向学校申请给我减免了费用。而我自己,也不并甘心就这样被“赶”进了城市。

因为经历了第一次的失败,那一年的复读时光,我学习更加认真,也懂得适当调整自己,成绩也一直稳定在年级前列。时间匆匆而过,转眼又到了高考季,因为是复读高考,总体感觉我比第一次稳当得多。不过因为是第二次高考,其实面临的压力比第一次更大。

让我没有想到的是,高考的前一天,居然在送考的人群里发现了父亲。远远看上去,父亲黑了很多,瘦了很多。父亲在考场外面租了个便宜的小旅馆,为了让我吃好,还特意从家里带了电饭锅,把从家里炒好的菜重新蒸热后让我吃。虽然高考期间的伙食比较好,但我觉得还是家里的饭菜更香。我知道,父亲是在用这样的方式,传递着家人对我的支持。

第二天早上,父亲送我到考场门口。他的话不多,只是拍了拍我的肩膀,说了句“放宽心态”。其实第一年高考更多的是败在了心态上。我看了看父亲,他的眼神里充满了信任和希望,走进考场,我心平静了很多,父亲的期许,于我而言更是一种力量。

每一堂考试出来和下一堂进考场前,我都能在人群中发现父亲。他依旧会轻轻地拍拍我的肩膀,那一拍,我觉得有无比的力量。

其实在我的印象里,父亲性格是比较孤僻的,生活的压力全落在他身上,他很少有情绪的表达。也正是这次高考,让我感到少有的父亲的温情。前前后后共三天,高考很快结束。虽然考得不是特别好,但我终究还是没有辜负父母的期望。

如今,多年过去了,我已经在城市立足,但我依然记得,高考那年,父亲拍拍我的肩膀,忠告我的那句“放宽心态”。虽然我知道有些路只能一个人走,但背后,依旧会有最可依靠的力量。

列表展示

主站展示位

使用 Rust 开发 Android 底层库,并简化 Java 与 Rust 相互操作 |

前言 提到JNI,大家都会想到C,C++.不过如今Rust又给我们增加了一个选项,借助rust的jni库( 关于 Rust 环境搭建、配置 Rust Android targets、linker,以及如何在 Android 上如何直接运行 Rust 代码,可以看上篇文章 将 Rust 编译为可在 Android 上使用的二进制文件 本文主要介绍如何使用 Rust 借助 J4RS 方便快捷的编写 Android Jni: 阅读本文,你需要具备、了解一下知识: Android 编写 JNI 的基本流程 Rust 代码基本的阅读能力 Android 开发的基本流程 Android 集成 Rust 配置 Rust Android Gradle Plugin Rust Android Gradle Plugin 这个 Gradle 插件的主要功能是帮你自动配置 Rust-Android 交叉编译,并将编译产物自动添加到 Android 项目。 这并不是必须的,你同样可以手动 build rust 项目。然后手动复制到 Android Studio 中使用。 因为我使用的是最新版本的 gradle , 采用 Kotlin kts 编写。在语法上稍有不同,旧版本写法可以在项目的 README 查看

Android中GPS定位(获取经纬度) |

AndroidGPS定位问题,众所周知是一个蛮麻烦的问题.当初我是新手,现在我也是新手,也搞了我头大,网上搜索了很多的例子,一直处于僵持阶段,而现在终于搞定了,因为我现在只需要获取到经纬度就可以了,反正获取经纬度可以从我这篇文章中看看;上代码。 在AndroidManifest.xml中加入权限: <uses-permission android:name=”android.permission.ACCESSFINELOCATION”/> <uses-permission android:name=”android.permission.ACCESSCOARSELOCATION”/>

RecyclerView里notifyItemRemoved的坑 |

RecyclerView很多时候是展示静态的数据,并不会有删除的操作,讲到RecyclerView时,会提到它提供了一个很好的展现删除操作动画的函数,代码片段一般是这样的 @Override public void onBindViewHolder(final CommonViewHolder holder, final int position) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { contentList.remove(position); notifyItemRemoved(position); } }); } 这样写的话,很快会产生数据删除错乱和超出索引异常导致崩溃。 原因是函数里面的传入的参数position,它是在进行onBind操作时确定的,在删除单项后,已经出现在画面里的项不会再有调用onBind机会,这样它保留的position一直是未进行删除操作前的postion值。 对于尚未进入画面的单项来说,它会使用新的position值,这个值是正确的,如果在单项里加上下面的代码 holder.textView.setText(contentList.get(position) + "#" + String.valueOf(position)); 在删除第一屏的一项后,向上滚动,会发现新滚上来的一行和它上面的一行的textview显示是一样的。 解决办法也很简单 先remove,再notifyItemRemoved, 最后再notifyItemRangeChanged remove:把数据从list中remove掉, notifyItemRemoved:显示动画效果 notifyItemRangeChanged:对于被删掉的位置及其后range大小范围内的view进行重新onBindViewHolder

unable to connect to 5555: connection refused |

I had the same issue since the android 6 upgrading. I noticed that for some reason the device is playing “hard to get” when you try to contact it over WIFI. Try these following steps: Make sure that Aggressive Wi-Fi to Cellular handover under Networking section in the device’s developer options is turned off. ping continuously from your pc to the device to make sure it’s not in network idle mode ping -t 192.

Flutter |

琥珀之月,空谷之兰,皆是孤芳,既是孤芳,但求自赏便罢!

Android ListView 与 RecyclerView 对比浅析—缓存机制 |

一,背景 RecyclerView是谷歌官方出的一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大和灵活。 最近,自己负责的业务,也遇到这样的一个问题,关于是否要将ListView替换为RecyclerView? 秉承着实事求是的作风,弄清楚RecyclerView是否有足够的吸引力替换掉ListView,我从性能这一角度出发,研究RecyclerView和ListView二者的缓存机制,并得到了一些较有益的”结论”,待我慢慢道来。 同时也希望能通过本文,让大家快速了解RecyclerView与ListView在缓存机制上的一些区别,在使用上也更加得心应手吧。 PS:相关知识: ListView与RecyclerView缓存机制原理大致相似,如下图所示: 过程中,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取,只是ListView与RecyclerView的实现细节有差异.(这只是缓存使用的其中一个场景,还有如刷新等) PPS:本文不贴出详细代码,结合源码食用更佳! 二. 正文 2.1 缓存机制对比 层级不同: RecyclerView比ListView多两级缓存,支持多个离ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。 具体来说: ListView(两级缓存): RecyclerView(四级缓存): ListView和RecyclerView缓存机制基本一致: 1). mActiveViews和mAttachedScrap功能相似,意义在于快速重用屏幕上可见的列表项ItemView,而不需要重新createView和bindView; 2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,目的是让即将进入屏幕的ItemView重用. 3). RecyclerView的优势在于a.mCacheViews的使用,可以做到屏幕外的列表项ItemView进入屏幕内时也无须bindView快速重用;b.mRecyclerPool可以供多个RecyclerView共同使用,在特定场景下,如viewpaper+多个列表页下有优势.客观来说,RecyclerView在特定场景下对ListView的缓存机制做了补强和完善。 缓存不同: 1). RecyclerView缓存RecyclerView.ViewHolder,抽象可理解为: View + ViewHolder(避免每次createView时调用findViewById) + flag(标识状态); 2). ListView缓存View。 缓存不同,二者在缓存的使用上也略有差别,具体来说: ListView获取缓存的流程: RecyclerView获取缓存的流程: 1). RecyclerView中mCacheViews(屏幕外)获取缓存时,是通过匹配pos获取目标位置的缓存,这样做的好处是,当数据源数据不变的情况下,无须重新bindView: 而同样是离屏缓存,ListView从mScrapViews根据pos获取相应的缓存,但是并没有直接使用,而是重新getView(即必定会重新bindView),相关代码如下: //AbsListView源码:line2345 //通过匹配pos从mScrapView中获取缓存 final View scrapView = mRecycler.getScrapView(position); //无论是否成功都直接调用getView,导致必定会调用createView final View child = mAdapter.getView(position, scrapView, this); if (scrapView != null) { if (child != scrapView) { mRecycler.

已经有女朋友了,又遇到更喜欢的对象怎么办? |

在知乎上开到这个问题,我只能说提问题的人,你还搞不懂“喜欢一个人”和“对一个人有感情”之间的区别。 我举两个不恰当的例子。比如说养狗,虚构两个情景。 情景一:  某天你去宠物市场闲逛,发现有一只泰迪很可爱,伶俐活泼聪明漂亮,还特别粘着你。你当时就动心了,打算买下它。  一问价格,要1500块钱。你身上没带这么多钱,也没带银行卡。当时是下午了,宠物市场马上要关门了。你只能第二天来买了。  于是你嘱咐店主千万不要卖给别人。一定要等你明天早上过来卖给你。店主答应了。 可你回家了还是不放心。晚上在床上都睡不着觉。生怕店主不守信用,把这狗狗卖给别人了。那感觉,就像是爱上了一个姑娘一样。  第二天一早,你就揣了1500块钱奔向宠物市场。  这次,你是从市场的另外一个门进去的,还没有走到昨天那个摊位,你突然发现了另外一只泰迪,比昨天那只更漂亮,更聪明,更可爱,更粘你,价格还更便宜,只要1200元。  我相信,只要你智商正常,你都会选择买1200的这一只。虽然,你为了1500的那一只牵挂了一晚上。但那又如何,遇上更好的,你立刻就移情别恋了。 我们都是这样的人。 因为,我们对那只泰迪,没有感情。 情景二:  某雨天你下班回家,看到一只流浪的小狗趴在你的家门前瑟瑟发抖。你一下子恻隐之心上来了,把它抱回家,给它洗澡,给它喂食,让它睡在毛毯子上。  从此,它就成了你的家人。  接下来的一年,每天早上是它叫你起床。每天你疲惫的下班回到家中,是它在门口等着你。你出去逛街,它走在你前面。有小偷偷你的包,它疯狂吠叫。你看电视,它就睡在你腿上。你上网,它就趴在你脚尖。 它已经成为了你生活的一部分。  一年后。有一个人,也不知道脑子怎么进水了,想要拿一只名贵的纯种狗狗来换你这只不值钱的收养的流浪狗。 你会换吗? 如果是我,当然不换。 因为我对它有感情了。 这就是感情。

Android热修复——原理 |

1.是用场景   当一个应用上线发布首,突然发现了一个bug需要进行修复,如果真个bug不是严重,或者可以通过服务端进行避免还好说。但是如果这个bug很严重,影响了主功能,必须更新才行,那重新打包,重新上传市场和渠道(近百的渠道)。这些还不是主要问题,用户刚刚升级现在又提示升级大大影响了用户体验。

Android 自定义相机自动对焦、二次对焦处理 |

由于android碎片化严重,而且各大厂商极有可能去修改相关API的实现,其中遇到了不少坑,包括实时相机高斯模糊,自动对焦的兼容问题,以及一系列性能问题。换过很多搜索引擎,访问过很多网站,访问过很多网站,拜读过很多代码,没有发现对于相机实时自动对焦特别完美的实现方式。现对相机的自动对焦问题单独做一个记录,算是对这部分的一个总结。也希望后人在这部分能够快速地解决问题,不必浪费过多的时间。测试手机包括:MX4 pro,小米4,华为荣耀3C等等。

Android5.0通知变化浅析 |

目前在Android中通知的使用还是很常见的,为了做版本兼容,常用兼容包NotificationCompat.Builder和 Notification.Builder。 NotificationCompat.Builder位于v4扩展包内(version 4 Support Library) Notification.Builder在Android 3.0 开始引入(API level 11). 最近在Android5.0设备上发现一个问题:通知图标突然变成了白色的方块而不是代码中设置的icon。 问题原因 细读开发者文档其实也可以发现一些线索,虽然笔者是直接查的源码发现的问题原因。部分介绍了几点关于通知的建议,其中的有两点是建议开发者不要做的行为。 Don’t Place any additional alpha (dimming or fading) into your small icons and action icons; they can have anti-aliased edges, but because Android uses these icons as masks (that is, only the alpha channel is used), the image should generally be drawn at full opacity. Don’t Use color to distinguish your app from others.

Android声明式UI框架 Litho 初探 ——两种数据类型 |

Litho中包含的的两种数据类型 Litho的两种属性分别是: 不可变属性称为Props 可变属性称为State 不可变属性Props 定义和使用props Props属性:Component中使用@Prop注解的参数集合,具有单向性和不可变性,可以在左右的方法中访问它的指。在同一个Component中我们可以定义和访问相同的prop 下面这个例子,定义了两个Prop,一个string类型text,一个int类型index,text的注解中optional = true表示它是一个可选参数。 当Component的生命周期方法被调用的时候,@Prop参数会保存component创建时从它们的父级传递过来的值(或者它们的默认值) 设置props prop参数其实在前几篇文章中都有使用过,用起来也没有什么特别的地方,这里不在赘述,制作一个简单的说明。 Component中的prop参数会在编译时候自动加入到Builder中,以上面的代码举例: PropComponent.create(c).index(10)./*text("测试文本").*/build() Prop的默认值 对于可选的Prop如果不设置值,就是java的默认值。或者你也可以使用@PropDefault注解然后添加默认值。 如果你使用Kotlin,那还需要加上@JvmFiel把该字段编辑为public才行。 @MountSpec object PropComponentSpec { @JvmField @PropDefault val prop1 = "default" @JvmField @PropDefault val prop2 = -1 资源类型 在Android开发中,我们经常会限定参数的类型。比如: fun doSomething(@ColorInt color: Int, @StringRes str: Int, @DimenRes width: Int){} 在Compontent的Prop中也有类似的操作,具体看代码: fun onMount( c: ComponentContext, textView: TextView, @Prop(optional = true,resType = ResType.STRING) text: String?

Typecho to Hugo |

这两天正式把博客从 typecho 转到 hugo 了。更准确的说应该是从动态博客转到了静态博客。 以前我是很抵制静态博客的。主要是感觉: 更新麻烦(现在仍然是这种感觉) 放在 github pages 上访问速度也不快,为了加速还需要套个 CDN。(同样是花钱,打折期间买个国内云服务器,速度不慢,还能干其他的) 配置真的很麻烦 这次换到 hugo 的起因是一个域名要备案,博客所在的域名要关闭评论系统,备案完后,打开评论发现,只要有评论的文章就卡死,然后 502。懒得折腾,直接关闭评论功能,发现关了后台也会卡死。索性转移到了 Hugo Hugo 如何安装配置网上很多这里不再赘述,主要说一下我是如何转换的。 部署在哪里 本来打算部署在腾讯对象存储 COS 上的,不过最后还是放弃了。 域名备案,内容审查。 不方便自动化处理,虽然通过github action + 云函数 + hook 可以做到更新仓库后自动构建,下载到 COS 但还是略显麻烦。需要配置好几个地方。 最终选择了部署在 在文章前面可以加很多参数的比如 --- title: "Typecho to Hugo" slug: "typecho-to-hugo" date: 2022-03-11T10:49:59+08:00 categories: [岁月如歌] tags: [Typecho,Hugo] showToc: true TocOpen: true draft: false # description: "Desc Text.

Don’t Store Data in the Application Object |

There is always some information that is needed in many places in your app. It can be a session token, the result of an expensive computation, etc. It is often tempting to avoid the overhead of passing objects between activities or keeping those in persistent storage. A pattern that is sometimes suggested is to dump your data in the Application object with the idea that it will be available across all activities.

Android-使用@AutoService实现spi |

什么是 SPI? Java SPI 全称 Service Provider Interface,是 Java 提供的一套用来被第三方实现或者扩展的 API,它可以用来启用框架扩展和替换组件。实际上是“基于接口的编程 + 策略模式 + 配置文件”组合实现的动态加载机制. 具体解释就是: 定义一个接口文件 写出多个该接口文件的实现 在 src/main/resources/ 下建立 /META-INF/services 目录, 新增一个以接口命名的文件 , 内容是要接口的实现类全路径 使用 ServiceLoader 类 来获取到这些实现的接口 示例 定义一个接口文件 - Book package com.apkdv.spi_test; public interface Book { String name(); } 实现两个接口 package com.apkdv.spi_test; public class Android implements Book { @Override public String name() { return "Android"; } } package com.

Flutter和原生Android控件对比 |

Flutter和原生Android控件对比: Flutter控件 Android控件 AppBar ActionBar/ToolBar ListView ListView/RecyclerView Text TextView Center ViewGroup FloatingActionButton FloatingActionButton(design库里面的) BottomNavigationBar BottomNavigation(design库里面的) RaisedButton/Button Button Column LinearLayout的android:orientation=“vertical” Row android:orientation=“horizontal” DecorationImage ImageView Image ImageView Stack FrameLayout/RelativeLayout Container RelativeLayout CustomMultiChildLayout RelativeLayout Algin alginParentXXX属性 resizeToAvoidBottomPadding android:windowSoftInputMode=”adjustResize属性 SingleChildScrollView ScrollView CustomScrollerView Recyclerview Image里面的BoxFit参数介绍:(相当于Android的ImageView的scaleType参数)

ViewModel之自定义构造函数 |

刚入坑架构组件没多久,发现很多基础性的东西理解起来是没什么问题的,但是一到具体使用就各种问题,相关实践文章也比较少,更多的只能靠自己解决 = =。今天无意间了解了AndroidViewModel的一个使用场景和实现原理,特地记录下来。 ###前言 一开始,跟着官方文档,ViewModel我们是这样实现的: public class MyViewModel entends ViewModel { //... } 然后是创建实例对象: MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class); 可以注意到,我们定义的ViewModel是没有构造函数的,也就是说如果遇到比较复杂情况下(需要在创建ViewModel时赋一些初始值),应该怎么办呢?总不能自己加一个构造函数,然后new出来吧,或者通过set方法一个一个加也行,但是这样就有点low了。于是,我发现了一个类AndroidViewModel AndroidViewModel AndroidViewModel这个类的定义很简单,它继承自ViewModel,然后添加了一个application私有属性: public class AndroidViewModel extends ViewModel { @SuppressLint("StaticFieldLeak") private Application mApplication; public AndroidViewModel(@NonNull Application application) { mApplication = application; } /** * Return the application. */ @SuppressWarnings("TypeParameterUnusedInFormals") @NonNull public <T extends Application> T getApplication() { //noinspection unchecked return (T) mApplication; } } 上面提到,很多时候我们需要在初始化ViewModel时需要传递一些参数,例如Activity中的一些参数等,但是根据ViewModel的生命周期我们知道,ViewModel中是不能传入Activity等实例对象的,因为在ViewModel存活的过程中,Activity是有可能会被销毁的。因此,Google爸爸推荐我们传入application。

Android全新支持库androidx |

如果使用最新版Android Studio 创建基于API28的项目,就会发现,原来的android.support.*全部变成了androidx.*??这是什么鬼?我们来看看Google的介绍 我们正在推出一种新的软件包结构,以便更清楚哪些软件包与Android操作系统捆绑在一起,并与您的应用程序的APK一起打包。展望未来,android.*软件包层次结构将保留给随操作系统提供的Android软件包; 其他包将在新的androidx.*包层次结构中发布。 正在重构现有包以使用新层次结构。历史文物 - 那些版本为27及更早版本,并打包为android.support.*- 将继续在Google Maven上提供; 但是,所有新开发都将发生在androidx.*从1.0.0开始版本化的新打包工件中。 有关所有旧类和构建工件的完整映射到新的,请参阅AndroidX重构页面。有关AndroidX重构的更多信息, 请参阅博客文章。 版本控制更改 新工件将遵循语义版本控制,并将独立更新,而不是一次更新。重组后,可以独立更新项目中的AndroidX库。这避免了将项目中的许多支持库模块从例如一次更新26.1.0到27.0.0所有支持库模块的问题。 新项目 如果使用androidx打包的依赖项创建新项目(而不是使用Android Studio工具重构现有项目),则新项目需要针对API级别28,并且您需要将以下行添加到您的gradle.properties文件中: android.useAndroidX=true android.enableJetifier=true 简而言之,support包会继续维护,但是所有新特性都会放到androidx中,如果想使用androidx,需要API为28(IDE应该也需要最新版本),同时gradle.properties中添加 android.useAndroidX=true android.enableJetifier=true,反之不想使用设置为false即可,需要注意的是即使依赖中不添加 implementation androidx.*相关的支持库,如果gradle.properties中设置为true 仍然使用androidx相关支持库,android.support相关引用会提示not found

博客寄语:

    从14年开始写博客,到现在再有2年就10年了。

实时播报:

博客号-学习成长

相信每一分耕耘都有每一分收获,致力帮助博客主所创作的博客能更快的被收录! 如果有其它需求,可联系下方邮箱。