opoojkk

Be open to new experiences!

FreshRSS API使用指南

不喜欢新闻客户端里带有政治倾向和无关紧要的娱乐新闻,诸如某某明星跌倒之类。日常都用rss阅读,可以阅读我常看的内容,FreshRSS又是可以自己部署的非常好用的服务,理所当然的用上了。 最近组了一台主机,重新安装FreshRSS之后总是也在reeder(iOS平台RSS阅读软件)上配置不了,记录一下。

Jetpack ViewModel实现原理

ViewModel和架构MVVM中的VM(ViewModel)同名,但并不是一个东西,架构中的ViewModel是和View双向绑定的,这里的ViewModel只能做到利用LiveData更新。 为什么用ViewModel呢?一是把网络请求和数据库读取的逻辑从Activity中放到了ViweModel,分担了一部分Activity的压力;另一个原因是可以在Activity或Fragment重建时保存数据,不会丢失。今天探讨的时第二个问题。

关于旅行的意义

我总是想弄清楚各种意义,仿佛没有意义的事物就不应该存在。时常看到有人分享各地的标志性建筑、食物或是服饰等等,单独拿出来分享的还是少数,更多的还是与某些东西合影的照片。即使去旅行的时间非常短,但一定会有那么两三个带标志性的,标志性物品和某个城市、某个地区、某种文化划上了等号。

Jetpack Lifecycle组件解析

Android中又越来越多组件依赖Lifecycle,从来不好奇Lifecycle是什么东西,又是怎么起作用的吗?我很好奇。 LifecycleOwner # 通常的用法往往是从LifecyclerOwner中拿到Lifecycle对象,之后add Oberver或者remove Observer。

Jetpack LiveData解析

Jetpack中最不陌生的大概就是LiveData了,LiveData的两个特点:和lifecycleOwner绑定且监听数据变化。用过的哪个不说好? 流程 # 常用的LiveData的形式大概是这样的:

理解Android屏幕适配和最小宽度

凡事总要问为什么。为什么需要屏幕适配? 众所周知,Android是一个较开发的系统,允许各家厂商定制修改AOSP,选用不同规格的硬件,包括CPU、内存、电池、传感器等等等等。当然屏幕也在其中。也因此,大家手上的手机屏幕大不相同,体现在屏幕的尺寸、分辨率上。

Material Design吸顶效果实现

前言 # Material Design是Google在2014年的I/O大会上发布的一种设计规范,包括布局、颜色、形状、声音、动效等。面向的是Android、iOS、Web和Flutter。对自己的Android,Google还推出了一系列组件、主题帮助开发者快速、方便的实现Material Design的效果。下面是几个能用在大部分实际项目中的控件:

Material Design滚动变色效果实现

许许多多Material风格的Android应用支持滚动后改变Action Bar和状态栏的颜色, 放一张示例图: 实现 # 外层ViewGroup改用CoordinatorLayout # CoordinatorLayout才支持内部View滚动后调用behavior的方法, 自定义View也能实现.

验证suspend all threads

验证suspend all threads # 对应KOOM实现流程, 结合对比几种场景, 验证KOOM中fork前suspend和resume后作用. suspend和resume # suspendAndFork 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pid_t HprofDump::SuspendAndFork() { KCHECKI(init_done_) if (android_api_ < __ANDROID_API_R__) { suspend_vm_fnc_(); } else if (android_api_ <= __ANDROID_API_S__) { void *self = __get_tls()[TLS_SLOT_ART_THREAD_SELF]; sgc_constructor_fnc_((void *)sgc_instance_.get(), self, kGcCauseHprof, kCollectorTypeHprof); ssa_constructor_fnc_((void *)ssa_instance_.get(), LOG_TAG, true); // avoid deadlock with child process exclusive_unlock_fnc_(*mutator_lock_ptr_, self); sgc_destructor_fnc_((void *)sgc_instance_.get()); } pid_t pid = fork(); if (pid == 0) { // Set timeout for child process alarm(60); prctl(PR_SET_NAME, "forked-dump-process"); } return pid; } resumeAndWait

COW与HProf文件格式分析

COW(copy on write) # Linux通过fork()和exec()函数族创建新进程。 为什么通过这种方式,而不是从头开始创建新进程? # Of course, one big question you might have: why would we build such an odd interface to what should be the simple act of creating a new process? Well, as it turns out, the separation of fork() and exec() is essential in building a UNIX shell, because it lets the shell run code after the call to fork() but before the call to exec(); this code can alter the environment of the about-to-be-run program, and thus enables a variety of interesting features to be readily built. The shell is just a user program4 . It shows you a prompt and then waits for you to type something into it. You then type a command (i.e., the name of an executable program, plus any arguments) into it; in most cases, the shell then figures out where in the file system the executable resides, calls fork() to create a new child process to run the command, calls some variant of exec() to run the command, and then waits for the command to complete by calling wait(). When the child completes, the shell returns from wait() and prints out a prompt again, ready for your next command. The separation of fork() and exec() allows the shell to do a whole bunch of useful things rather easily. For example: prompt> wc p3.c > newfile.txt In the example above, the output of the program wc is redirected into the output file newfile.txt (the greater-than sign is how said redirection is indicated). The way the shell accomplishes this task is quite simple: when the child is created, before calling exec(), the shell (specifically, the code executed in the child process) closes standard output and opens the file newfile.txt. By doing so, any output from the soonto-be-running program wc is sent to the file instead of the screen (open file descriptors are kept open across the exec() call, thus enabling this behavior [SR05]).