JavaScript Promise

Promise 是一个构造函数,通过 new 关键字实例化对象

Promise 语法

1
2
3
const p = new Promise((resolve, reject)=>{})

console.dir(p)
  • Promise 接受一个函数作为参数
  • 在参数函数中接受两个参数
    • resolve:
    • reject:

Promise 实例

promise 实例有两个属性

  • state:状态
  • result:结果
  1. Promise 的状态
  1. pending
  2. fulfilled
  3. rejected
  1. Promise 状态的改变

通过调用 resolve()reject() 改变当前 promise 对象的状态

1
2
3
4
5
6
const p = new Promise((resolve, reject)=>{
// reslove() 调用函数,是当前 promise 对象的状态变为 fulfilled
resolve()
})

console.dir(p) //fulfilled
1
2
3
4
5
6
const p = new Promise((resolve, reject)=>{
// reject() 调用函数,是当前 promise 对象的状态变为 rejected
reject()
})

console.dir(p) //rejected

promise 的状态改变时一次性的

1
2
3
4
5
6
const p = new Promise((resolve, reject)=>{
resolve()
reject()
})

console.dir(p) //fulfilled
  1. Promise 的结果
1
2
3
4
5
const p = new Promise((resolve, reject)=>{
resolve('Success')
})

console.dir(p)

Promise 的使用

1) then 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const p = new Promise((resolve, reject)=>{
resolve('Success')
})
// then 是一个函数
// 接受两个函数参数
// 返回结果为一个新的 promise 对象
p.then(()=>{
// promise 状态为 fulfilled 时调用
console.log("成功时调用")
},()=>{
// promise 状态为 rejected 时调用
console.log("失败时调用")
})
console.dir(p)

1
2
3
4
5
6
7
8
9
10
11
const p = new Promise((resolve, reject)=>{
resolve('Success')
})
p.then((res)=>{
console.log(res)
console.log("成功时调用")
},(err)=>{
console.log(err)
console.log("失败时调用")
})
console.dir(p)
1
2
3
4
5
6
7
8
9
10
11
const p = new Promise((resolve, reject)=>{
resolve('Success')
})
const r = p.then((res)=>{
console.log(res)
console.log("成功时调用")
},(err)=>{
console.log(err)
console.log("失败时调用")
})
console.dir(r)

then 返回结果为一个新的 promise 对象, 状态为 pending

1
2
3
4
5
6
7
const t = new Promise((resolve, reject) => {}).then((res)=> {
conlose.log('Success')
},(err)=>{
conlose.log('Fail')
})

console.dir(t)

如果 promise 的状态不改变, then 函数里的方法不执行

  1. catch
1
2
3
4
5
6
7
8
9
const p = new Promise((resolve, reject) => {
reject()
})

p.catch(()=>{
console.log('Failure')
})

console.dir(p)
1
2
3
4
5
6
7
8
9
const p = new Promise((resolve, reject) => {
console.log(a)
})

p.catch((erro)=>{
console.log('Failure = ' + erro)
})

console.dir(p)

参考:

2020最好理解的Promise教程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

Redis 学习笔记

Redis - 配置文件 - InfoQ 写作平台

在面试前必须要知道的 Redis 面试内容 | Laravel China 社区 (learnku.com)

带你彻底搞懂 Redis 16大应用场景! - SegmentFault 思否

Redis 实战篇:巧用数据类型实现亿级数据统计 - SegmentFault 思否

string (字符串)

  • 单值缓存

    SET key value

    GET key

  • 对象缓存

    1)SET user:1 value(json 格式数据)

    ​ GET user:1

    2)MSET user:1:name Lily user:1:balance 999

    ​ MGET user:1:name user:1:balance

    ​ MGET user:1:name

  • 分布式锁

    SETNX

  • 计数器

    INCR article:readCount:{文章ID}

    GET article:readCount:{文章ID}

  • WEB 集群 session 共享

  • 分布式全局序列号

    INCBY orderId 1000 //redis 批量生成序列号

hash(哈希)

  • 对象缓存

    HSET key field value

    HMSET key field value [field value …]

  • 电商购物车

    1、用户 ID 为 key

    2、商品 ID 为 field

    3、商品数量为 value

    购物车操作:

    1、添加商品 hset cart:1001 10088 1

    2、增加数量 hincrby cart:1001 10088 1

    3、商品总数 hlen cart:1001 10088

    4、删除商品 hdel cart:1001 10088

    5、获取购物车所有商品 hgetall cart:1001

    缺点:

    1)过期功能不能用在 field 上,只能用在 key 上

    2)Redis 集群架构下不适合大规模使用

list (列表)

LPUSH key value [value…]

RPUSH key value [value…]

LPOP key

RPOP key

LRANGE key start stop

实现常用数据结构

Stack(栈)= LPUSH + LPOP -> FILO

Queue(队列)= LPUSH + RPOP

BLocking MQ(阻塞队列)= LPUSH + BRPOP

实现消息流

set(集合)

set 常用操作

set 常用计算

应用场景

1、抽奖

1)点击参与抽奖加入集合

1
SADD key {userId}

2)查看参与抽奖所有用户

1
SMEMBERS key

3)抽取 count 名中奖者

1
2
3
4
SRANDMEMBER key count

//分批抽奖
SPOP key count

2、微信微博点赞、收藏、标签

1)点赞

1
SADD like:{消息 ID} {用户 ID}

2)取消点赞

1
SREM like:{消息 ID} {用户 ID}

3)检查用户是否点过赞

1
SISMEMBER like:{消息 ID} {用户 ID}

4)获取点赞的用户列表

1
SMEMBERS like:{消息 ID} 

5)获取点赞用户数

1
SCARD like:{消息 ID} 

3、集合操作实现微博等关注模型

zset(有序集合)

应用

1、实现排行榜

Weiwf/redis-mindmap: 通过思维导图整理redis的重要知识点 (github.com)

dpkg: warning: files list file for package 'xxxx' missing; assuming package has no files currently installed

2021-06-18,找到最佳的解决办法:

新建 dpkg-warning-fix.sh 文件,编辑内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
set -e


# Clean out /var/cache/apt/archives
apt-get clean
# Fill it with all the .debs we need
apt-get --reinstall -dy install $(dpkg --get-selections | grep '[[:space:]]install' | cut -f1)


DIR=$(mktemp -d -t info-XXXXXX)
for deb in /var/cache/apt/archives/*.deb
do
# Move to working directory
cd "$DIR"
# Create DEBIAN directory
mkdir -p DEBIAN
# Extract control files
dpkg-deb -e "$deb"
# Extract file list, fixing up the leading ./ and turning / into /.
dpkg-deb -c "$deb" | awk '{print $NF}' | cut -c2- | sed -e 's/^\/$/\/./' > DEBIAN/list
# Figure out binary package name
DEB=$(basename "$deb" | cut -d_ -f1)
# Copy each control file into place
cd DEBIAN
for file in *
do
cp -a "$file" /var/lib/dpkg/info/"$DEB"."$file"
done
# Clean up
cd ..
rm -rf DEBIAN
done
rmdir "$DIR"

原理是重新下载所有安装过的软件包,然后从中提取文件列表信息复制到info文件夹里。(所以请在网速较好的时候使用)

1
sudo ./dpkg-warning-fix.sh

参考:

[dpkg: warning: files list file for package `*****’-爱开源 (aikaiyuan.com)](https://www.aikaiyuan.com/9147.html)


经验不足,按网上的教程操作,把 /var/lib/dpkg/info/ 的文件删除了,之后安装软件就会频繁出现如下警告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dpkg: warning: files list file for package 'python-apt-common' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'zerofree' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'aufs-tools' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libnpth0:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'fdisk' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libhtml-tagset-perl' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'iputils-ping' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'ubuntu-advantage-tools' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libedit2:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'python3-cryptography' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libpam-runtime' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'vim-tiny' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libncurses5:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libtool' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libcom-err2:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libgomp1:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'dmeventd' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libpgm-5.2-0:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libatomic1:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'libpython3-stdlib:amd64' missing; assuming package has no files currently installed
dpkg: warning: files list file for package 'liblxc1' missing; assuming package has no files currently installed

......

解决办法:

新建 dpkg-warning.txt 文件,并把上述提示全部拷贝到 该文件中:

1
vi dpkg-warning.txt

新建 dpkg-warning-fix.sh 文件,编辑内容:

1
2
3
4
5
6
#!/bin/bash

for package in $(cat dpkg-warning.txt | grep "dpkg: warning: files list file for package " | grep -Po "'[^']*'" | sed "s/'//g");
do
apt install --reinstall "$package";
done
1
chmod 777 dpkg-warning-fix.sh
1
./dpkg-warning-fix.sh

参考:

https://blog.csdn.net/taosera/article/details/79420257~~~

Android Styling: Themes Overlay

In previous articles in this series on Android styling, we’ve looked at the difference between styles and themes, talked about the benefits of using themes and theme attributes and highlighted some common attributes to use.

Today we’ll focus on actually using themes, how they are applied to your app and the implications for how you build them.

Scope

In a previous article we stated:

A Theme is accessed as a property of a Context and can be obtained from any object which is or has a context e.g. Activity, View or ViewGroup. These objects exist in a tree, where an Activity contains ViewGroups which contain Views etc. Specifying a theme at any level of this tree cascades to descendent nodes e.g. setting a theme on a ViewGroup applies to all the Views within it (in contrast to styles which only apply to a single view).

Setting a theme at any level in this tree doesn’t replace the theme currently in effect, it overlays it. Consider the following Button which species a theme, but who’s parent also specifies a theme:

1
2
3
4
5
6
7
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<ViewGroup
android:theme="@style/Theme.App.Foo">
<Button
android:theme="@style/Theme.App.Bar"/>
</ViewGroup>

themes_overlay_nested.xml hosted with ❤ by GitHub

If an attribute is specified in both themes, then the most local “wins” i.e. those in Bar will be applied to the button. Any attributes specified in theme Foo but not specified in theme Bar will also be applied to the button.

Themes overlay each other

This might seem like a contrived example but this technique is extremely useful for styling subsections of an app with a different appearance such as a dark toolbar on an otherwise light screen, or this screen (from the Owl sample app) which has a largely pink theme but the bottom section showing related content has a blue theme:

A blue sub-section within a pink themed screen.

This can be achieved by setting a theme on the root of the blue section and it cascades to all views within it.

Overly Overlaid

As themes overlay any themes higher in the tree, it’s important to consider what your theme specifies to ensure that it doesn’t accidentally replace an attribute that you want to keep. For example, you may want to change the background color of a view (usually controlled by colorSurface) but nothing else i.e. you want to retain the rest of the current theme. For this we can use a technique known as theme overlays.

These are themes which are designed to, well, overlay another theme. They are as narrowly scoped as possible i.e. they only define (or inherit) as few attributes as possible. In fact, theme overlays often (but not always) have no parent e.g.:

1
2
3
4
5
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<style name="ThemeOverlay.MyApp.DarkSurface" parent="">
<item name="colorSurface">#121212</item>
</style>

themes_overlay_themeoverlay.xml hosted with ❤ by GitHub

Theme overlays are narrowly scoped themes, defining as few attributes as possible, designed to overlay another theme

By convention, we name these beginning with “ThemeOverlay”. There are a number of handy theme overlays provided by MDC (and AppCompat) that you can use to flip the color of a subsection of your app from light to dark:

  • ThemeOverlay.MaterialComponents.Dark
  • ThemeOverlay.MaterialComponents.Light

By definition, theme overlays don’t specify a number of things and shouldn’t be used in isolation e.g. as the theme of your activity. In fact you can think of 2 “types” of theme you can use in your app:

  1. “Full” themes. These specify everything you’d need for a screen. They inherit from another “full” theme like Theme.MaterialComponents and should be used to theme an Activity.
  2. Theme overlays. Only ever intended to be applied over a full theme, i.e. should not be used in isolation as likely won’t specify important and necessary things.

Ever-present

There’s always a theme in effect, even if you don’t specify one anywhere in your app you’ll inherit a default theme. As such the example above was a simplification and you should never use a full theme within a View and instead use theme overlays:

1
2
3
4
5
6
7
8
9
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<ViewGroup …
- android:theme="@style/Theme.App.Foo">
+ android:theme="@style/ThemeOverlay.App.Foo">
<Button …
- android:theme="@style/Theme.App.Bar"/>
+ android:theme="@style/ThemeOverlay.App.Bar"/>
</ViewGroup>

themes_overlay_use_overlays.xml.diff hosted with ❤ by GitHub

These overlays won’t exist in isolation but will themselves be overlaid on the theme of the enclosing Activity.

Cost : Benefit

Using Themes has a run-time cost; each time that you declare an android:theme, you’re creating a new ContextThemeWrapper, which allocates new Theme and Resources instances. It also introduces more levels of styling indirection to be resolved. Be wary of using themes too liberally, especially in repeated situations such as RecyclerView item layouts or profile to monitor their impact.

Use in Context

We said that a Theme is associated with a Context — this means that if you’re using a Context to retrieve a resource in code, then be careful that you use the right Context. For example, somewhere in your code you may retrieve a Drawable:

1
someView.background = AppCompatResources.getDrawable(requireContext(), R.drawable.foo)

If the drawable references a theme attribute (which all drawables can do from API 21+, and VectorDrawables can do from API 14+ via Jetpack) then you should ensure you use the right Context to load the Drawable. If you don’t you might be frustrated when trying to apply a theme to a sub-hierarchy and wondering why your Drawable isn’t respecting it. For example if you use a Fragment or Activity’s Context to load the Drawable, this won’t respect themes applied lower down in the tree. Instead use the Context closest to where the resource will be used:

1
someView.background = AppCompatResources.getDrawable(someView.context, R.drawable.foo)

Mis-Application

We’ve talked about themes and contexts existing in a tree: Activity > ViewGroup > View etc. It can be tempting to extend this mental model to include the Application class, after all you can specify a theme on the <application> tag in your manifest. Don’t be fooled by this!!

The Application Context does not retain any theme information, the theme that you can set in your manifest is merely used as a fallback for any Activity which doesn’t explicitly set a theme. As such you should never use the Application Context to load resources which might vary by theme (like drawables or colors) or to resolve theme attributes.

Never use the *Application* *Context* to load themable resources

This is also why we specify a “full” theme for an Activity and structure these to extend from any application wide theme — an <activity>’s theme isn’t overlaid over the <application>’s.

Build up

Hopefully this post has explained how themes overlay ancestors in a tree and how this behavior can be useful when styling our apps. Use the android:theme tag to theme sections of your layout and use theme overlays to only adjust the attributes you need. Be mindful of using the right theme and context to load resources and be wary of the application context!

https://medium.com/androiddevelopers/android-styling-themes-overlay-1ffd57745207

Android Styling: Prefer Theme Attributes

In the previous posts in this series on Android styling, we looked at the difference between themes and styles and why it’s a good idea to factor out things that you wish to vary by theme and common theme attributes to use:

Android Styling: Themes vs StylesThe Android styling system offers a powerful way to specify your app’s visual design, but it can be easy to misuse…medium.com

Android Styling: Common Theme AttributesIn the previous article in this series on Android styling, we looked at the difference between themes and styles and…medium.com

This enables us to create fewer layouts or styles, isolating changes within a theme. In practice, you largely want to vary colors by theme and as such you should always* refer to colors via theme attributes.

Always* refer to colors via theme attributes

That means you can consider code like this to be a smell:

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<View
android:background="@color/white"/>

prefer_theme_attrs_color_res.xml hosted with ❤ by GitHub

Instead you should refer to a theme attribute, allowing you to vary the color by theme, for example, providing a different value in dark theme:

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<View
android:background="?attr/colorSurface"/>

prefer_theme_attrs_color_attr.xml hosted with ❤ by GitHub

Even if you’re not currently supporting alternate themes (what–no dark theme??), I’d recommend following this approach as it’ll make adopting theming much easier.

Qualified Colors?

You can vary colors by providing alternate values in different configurations (e.g. @color/foo defined in both res/**values**/colors.xml and an alternate value set in res/**values-night**/colors.xml) but I’d recommend using theme attributes instead.

Varying at the color layer forces you to give semantic names to colors i.e. you likely wouldn’t name a color @color/white and provide a dark variant in the -night configuration — that would be pretty confusing. Instead you might be tempted to use a semantic name, like @color/background. The problem with this is that it combines both the declaration of the color and providing the value. As such it gives no indication that this can or will vary by theme.

Varying @colors can also encourage you to create more colors. If a different situation calls for a new semantically named color with the same value (i.e. not a background but should be the same color), then you still need to create a new entry in your colors file.

By using a theme attribute we separate the declaration of semantic colors from providing their values and make call-sites clearer that the color will vary by theme (as they use the ?attr/ syntax). Keeping your color declarations to literally named values encourages you to define a palette of colors used by your app and vary them at the theme level, keeping your colors file small and maintainable.

Define a palette of colors used by your app and vary them at the theme level

The added benefit of this approach is that layouts/styles referring to these colors become more reusable. Because themes can be overlaid or varied, the indirection means you don’t need to create alternate layouts or styles just to vary some colors — you can use the same layouts with a different theme.

Always?

I placed an asterix on “always* refer to colors via theme attributes” because there may be occasions where you explicitly don’t want to vary a color by theme. For example, the Material Design guidelines call out occasions where you may wish to use the same brand color in both light and dark themes.

In these rare cases, it’s perfectly valid to refer directly to a color resource:

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<FloatingActionButton
app:backgroundTint="@color/owl_pink_500"/>

prefer_theme_attrs_constant_color_exception.xml hosted with ❤ by GitHub

State of the art

Another situation where you might not refer directly to a theme attribute in your layouts/styles is when using ColorStateLists.

1
2
3
4
5

<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<View
android:background="@color/primary_20"/>

prefer_theme_attrs_csl_exception.xml hosted with ❤ by GitHub

This might be valid if primary_20 is a ColorStateList which itself refers to theme attributes for the color values (see below). While commonly used to provide different colors in different states (pressed, disabled etc) ColorStateLists have another capability that can be useful for theming. They let you specify an alpha value to be applied to a color:

1
2
3
4
5
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<selector
<item android:alpha="0.20" android:color="?attr/colorPrimary" />
</selector>

prefer_theme_attrs_csl.xml hosted with ❤ by GitHub

This kind of single-item-ColorStateList (i.e. only supplying a single, default color, not different colors per state) helps reduce the number of color resources that you need to maintain. That is rather than defining a new color resource that manually sets an alpha value on your primary color (per configuration!) instead this alters whatever colorPrimary is in the current theme. If your primary color changes you only need to update it in a single place, not hunting down all instances of where it has been tweaked.

While useful, there are some caveats to this technique to be aware of.

\1. If the specified color also has an alpha value, then the alphas are combined e.g. applying 50% alpha to 50% opaque white would yield 25% white:

1
2
3
4
5
6

<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<selector
<item android:alpha="0.50" android:color="#80ffffff" />
</selector>

prefer_theme_attrs_csl_combined_alpha.xml hosted with ❤ by GitHub

For this reason, it’s preferable to specify theme colors as fully opaque and use ColorStateLists to modify their alphas.

\2. The alpha component was only added in API 23 so if your min sdk is lower than this, be sure to use AppCompatResources.getColorStateList which backports this behavior (and always use the android:alpha namespace, never the app:alpha namespace).

\3. Often we use a shorthand to set a color as a drawable e.g.

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<View
android:background="@color/foo"/>

prefer_theme_attrs_view_background_color.xml hosted with ❤ by GitHub

A View’s background is a drawable, this shorthand coerces the given color to a ColorDrawable. However there is no way to convert a ColorStateList to a Drawable (before API 29 when ColorStateListDrawable was introduced to solve this issue). We can however work around this restriction:

1
2
3
4
5
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<View
android:background="@drawable/a_solid_white_rectangle_shape_drawable"
app:backgroundTint="@color/some_color_state_list"/>

prefer_theme_attrs_view_background_tint.xml hosted with ❤ by GitHub

Be sure that your background tint supports the states your view needs e.g. if it needs to change when disabled.

Enforcement

So you’re convinced that you should be using theme attributes and ColorStateLists, but how do you enforce this across your codebase or team? You can try to be vigilant during code reviews but this doesn’t scale well. A better approach is to rely on tooling to catch this. This article outlines how to add a lint check to look for literal color uses and could be extended to cover all advice in this article:

Making Android Lint Theme AwareUse Android Lint API to identify screens and drawable not ready for dark theme. Also, use it to maintain dark theme…proandroiddev.com

Be Indirect

Using theme attributes and ColorStateLists to factor colors out to your theme makes your layouts and styles more flexible, promoting reuse and keeping your codebase lean and maintainable.

Join us in the next post where we’ll look more at using themes and how they interact:

Android Styling: Themes OverlayIn previous articles in this series on Android styling, we’ve looked at the difference between styles and themes…medium.com

https://medium.com/androiddevelopers/android-styling-prefer-theme-attributes-412caa748774

Android Styling: Common Theme Attributes

In the previous article in this series on Android styling, we looked at the difference between themes and styles and how themes allow you to write more flexible styles and layouts which isolate changes:

Android Styling: Themes vs StylesThe Android styling system offers a powerful way to specify your app’s visual design, but it can be easy to misuse…medium.com

Specifically we recommended using theme attributes to provide a point of indirection to resources, so that you can vary them (e.g. in dark theme). That is, if you find yourself writing a direct resource reference (or worse yet, a hardcoded value 😱) in a layout or style, consider if you should use a theme attribute instead.

1
2
3
4
5
6
7
8

<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<ConstraintLayout ...
- android:foreground="@drawable/some_ripple"
- android:background="@color/blue" />
+ android:foreground="?attr/selectableItemBackground"
+ android:background="?attr/colorPrimarySurface" />

common_theme_attrs_prefer.xml.diff hosted with ❤ by GitHub

But what theme attributes are available to use? This post highlights the common ones that you should know about; those that come from Material, AppCompat or the platform. This is not a complete list (for that I’d recommend browsing the attrs files linked below where they are defined) but these are the attributes that I use all the time.

Colors

Many of these colors come from the Material color system, which defines semantic names for colors that you can use throughout your app (implemented as theme attrs).

  • ?attr/colorPrimary The primary branding color for the app.
  • ?attr/colorSecondary The secondary branding color for the app, usually a bright complement to the primary branding color.
  • ?attr/colorOn[Primary, Secondary, Surface etc] A color which contrasts against the named color.
  • ?attr/color[Primary, Secondary]Variant An alternate shade of the given color.
  • ?attr/colorSurface A color for surfaces of components, such as cards, sheets, and menus.
  • ?android:attr/colorBackground The background for the screen.
  • ?attr/colorPrimarySurface switches between colorPrimary in the Light themes, colorSurface in the Dark theme.
  • ?attr/colorError A color for displaying errors.

Other handy colors:

  • ?attr/colorControlNormal The color applied to icons/controls in their normal state.
  • ?attr/colorControlActivated The color applied to icons/controls in their activated state (e.g. checked).
  • ?attr/colorControlHighlight The color applied to control highlights (e.g. ripples, list selectors).
  • ?android:attr/textColorPrimary The most prominent text color.
  • ?android:attr/textColorSecondary Secondary text color.

Dimens

  • ?attr/listPreferredItemHeight Standard (min) height for list items.
  • ?attr/actionBarSize The height of a toolbar.

Drawables

  • ?attr/selectableItemBackground A ripple/highlight for interactive items (also handy for foregrounds!!)
  • ?attr/selectableItemBackgroundBorderless An unbounded ripple.
  • ?attr/dividerVertical A drawable that may be used as a vertical divider between visual elements.
  • ?attr/dividerHorizontal A drawable that may be used as a horizontal divider between visual elements.

TextAppearances

Material defines a type scale — a discrete set of text styles that you should use throughout your app, each of which is provided as a theme attribute which can be set as a textAppearance. Check out the Material type scale generator to help generate a scale for different fonts.

  • ?attr/textAppearanceHeadline1 defaults to light 96sp text.
  • ?attr/textAppearanceHeadline2 defaults to light 60sp text.
  • ?attr/textAppearanceHeadline3 defaults to regular 48sp text.
  • ?attr/textAppearanceHeadline4 defaults to regular 34sp text.
  • ?attr/textAppearanceHeadline5 defaults to regular 24sp text.
  • ?attr/textAppearanceHeadline6 defaults to medium 20sp text.
  • ?attr/textAppearanceSubtitle1 defaults to regular 16sp text.
  • ?attr/textAppearanceSubtitle2 defaults to medium 14sp text.
  • ?attr/textAppearanceBody1 defaults to regular 16sp text.
  • ?attr/textAppearanceBody2 defaults to regular 14sp text.
  • ?attr/textAppearanceCaption defaults to regular 12sp text.
  • ?attr/textAppearanceButton defaults to medium all caps 14sp text.
  • ?attr/textAppearanceOverline defaults to regular all caps 10sp text.

Shape

Material employs a shape system which is implemented as theme attrs for small, medium and large components. Note that if you’re setting a shape appearance on a custom component, you likely want to use a MaterialShapeDrawable as it’s background which understands and implements the shaping.

  • ?attr/shapeAppearanceSmallComponent used for Buttons, Chips, Text Fields etc. Defaults to rounded 4dp corners.
  • ?attr/shapeAppearanceMediumComponent used for Cards, Dialogs, Date Pickers etc. Defaults to rounded 4dp corners.
  • ?attr/shapeAppearanceLargeComponent used for Bottom Sheets etc. Defaults to rounded 0dp corners (i.e. square!)

Button Styles

This might seem super specific, but Material defines three types of buttons: Contained, Text and Outlined. MDC offers theme attrs that you can use to set the style of a MaterialButton:

  • ?attr/materialButtonStyle defaults to contained (or just omit the style).
  • ?attr/borderlessButtonStyle for a text style button.
  • ?attr/materialButtonOutlinedStyle for outlined style.

Floats

  • ?android:attr/disabledAlpha Default disabled alpha for widgets.
  • ?android:attr/primaryContentAlpha The alpha applied to the foreground elements.
  • ?android:attr/secondaryContentAlpha The alpha applied to secondary elements.

App vs Android namespace

You might have noticed that some attributes are referenced by
?**android**:attr/foo and others just by ?attr/bar. This is because some are defined by the Android platform, and as such you need the android part to reference them by their namespace (just like with view attributes in layouts: android:id). Those without come from static libraries (i.e. AppCompat or MDC) which are compiled into your application, so don’t need the namespace (similar to how you might use app:baz in a layout). Some elements are defined both in the platform and in a library e.g. colorPrimary. In these cases, prefer the non-platform version, as this can be used on all API levels i.e. they’re duplicated in a library precisely to backport them. In these cases, I’ve listed the non-platform versions above.

prefer non-platform attributes which can be used on all API levels

More Resources

For a complete list of the theme attributes available to use, go to the source of truth:

Material Design Components:

Do It Yourself

Sometimes there isn’t a theme attribute which abstracts something you’d like to vary by theme. No worries… create your own! Here’s an example from the Google I/O app which shows a list of conference sessions in two screens.

Two screens listing conference sessions

They’re largely similar but the left screen must leave space for the sticky time headers while the right screen does not. We implemented this by abstracting where to align items behind a theme attribute so that we can vary them by theme and use the same layout across two different screens:

\1. Define the theme attribute in attrs.xml

1
2
3
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<attr name="sessionListKeyline" format="dimension" />

common_theme_attrs_custom_attr.xml hosted with ❤ by GitHub

\2. Provide different values in different themes:

1
2
3
4
5
6
7
8
9
10
11
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.IOSched.Schedule">

<item name="sessionListKeyline">72dp</item>
</style>

<style name="Theme.IOSched.Speaker">

<item name="sessionListKeyline">16dp</item>
</style>

common_theme_attrs_custom_attr_values.xml hosted with ❤ by GitHub

\3. Use the theme attr in the single layout used on both screens (each using one of the above themes):

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<Guideline
app:layout_constraintGuide_begin="?attr/sessionListKeyline" />

common_theme_attrs_custom_attr_usage.xml hosted with ❤ by GitHub

Question (mark) everything

Knowing what theme attributes are available, equips you to use them when writing your layouts, styles or drawables. Using theme attributes makes it much easier to support theming (like dark theme) and to write more flexible, maintainable code. For a deep dive on this, join us in our next post in this series:

Android Styling: Prefer Theme AttributesTheme attribute all the thingsmedium.com

https://medium.com/androiddevelopers/android-styling-common-theme-attributes-8f7c50c9eaba

Android Styling: Themes vs Styles

The Android styling system offers a powerful way to specify your app’s visual design, but it can be easy to misuse. Proper use of it can make themes and styles easier to maintain, make branding updates less scary and make it straightforward to support dark modes. This is the first in a series of articles where Chris Banes and I will set out to demystify Android styling so that you can make stylish apps without pulling your hair out.

In this first article, I’ll take a look at the building blocks of the styling system: themes and styles.

Theme != Style

Both themes and styles use the same <style> syntax but serve very different purposes. You can think of both as key-value stores where the keys are attributes and the values are resources. Let’s take a look at each.

What’s in a style?

A style is a collection of view attribute values. You can think of a style as a Map<**view** attribute, resource>. That is the keys are all view attributes i.e. attributes that a widget declares and you might set in a layout file. Styles are specific to a single type of widget because different widgets support different sets of attributes:

Styles are a collection of view attributes; specific to a single type of widget

1
2
3
4
5
6
7
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<style name="Widget.Plaid.Button.InlineAction" parent="…">
<item name="android:gravity">center_horizontal</item>
<item name="android:textAppearance">@style/TextAppearance.CommentAuthor</item>
<item name="android:drawablePadding">@dimen/spacing_micro</item>
</style>

themes_vs_styles_style.xml hosted with ❤ by GitHub

As you can see, each of the keys in the style are things you could set in a layout:

1
2
3
4
5
6
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<Button
android:gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.CommentAuthor"
android:drawablePadding="@dimen/spacing_micro"/>

themes_vs_styles_view_attrs.xml hosted with ❤ by GitHub

Extracting them to a style makes it easy to reuse across multiple views and maintain.

Usage

Styles are used by individual views from a layout:

1
2
3
4
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<Button
style="@style/Widget.Plaid.Button.InlineAction"/>

themes_vs_styles_style_usage.xml hosted with ❤ by GitHub

Views can only apply a single style — contrast this to other styling systems such as css on the web where components can set multiple css classes.

Scope

A style applied to a view only applies to that view, not to any of its children. For example, if you have a ViewGroup with three buttons, setting the InlineAction style on the ViewGroup will not apply that style to the buttons. The values provided by the style are combined with those set directly in the layout (resolved using the styling precedence order).

What’s a theme?

A theme is a collection of named resources which can be referenced later by styles, layouts etc. They provide semantic names to Android resources so you can refer to them later e.g. colorPrimary is a semantic name for a given color:

1
2
3
4
5
6
7
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.Plaid" parent="…">
<item name="colorPrimary">@color/teal_500</item>
<item name="colorSecondary">@color/pink_200</item>
<item name="android:windowBackground">@color/white</item>
</style>

themes_vs_styles_theme.xml hosted with ❤ by GitHub

These named resources are known as theme attributes, so a theme is Map<**theme** attribute, resource>. Theme attributes are different from view attributes because they’re not properties specific to an individual view type but semantically named pointers to values which are applicable more broadly in an app. A theme provides concrete values for these named resources. In the example above the colorPrimary attribute specifies that the primary color for this theme is teal. By abstracting the resource with a theme, we can provide different concrete values (such as colorPrimary=orange) in different themes.

Themes are a collection of named resources, useful broadly across an app

A theme is similar to an interface. Programming to an interface allows you to decouple the public contract from the implementation allowing you to provide different implementations. Themes play a similar role; by writing our layouts and styles against theme attributes, we can use them under different themes, providing different concrete resources.

Roughly equivalent pseudo-code:

1
2
3
4
5
6
7
8
9
10
/* Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 */
interface ColorPalette {
@ColorInt val colorPrimary
@ColorInt val colorSecondary
}

class MyView(colors: ColorPalette) {
fab.backgroundTint = colors.colorPrimary
}

themes_vs_styles_theme_psuedo_interface.kt hosted with ❤ by GitHub

Which allows you to vary the way that MyView is rendered, without having to create variants of it:

1
2
3
4
5
/* Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 */
val lightPalette = object : ColorPalette { … }
val darkPalette = object : ColorPalette { … }
val view = MyView(if (isDarkTheme) darkPalette else lightPalette)

themes_vs_styles_theme_psuedo_interface_usage.kt hosted with ❤ by GitHub

Usage

You can specify a theme on components which have (or are) a Context e.g. Activity or Views/ViewGroups:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->

<!-- AndroidManifest.xml -->
<application
android:theme="@style/Theme.Plaid">
<activity
android:theme="@style/Theme.Plaid.About"/>

<!-- layout/foo.xml -->
<ConstraintLayout
android:theme="@style/Theme.Plaid.Foo">

themes_vs_styles_theme_usage.xml hosted with ❤ by GitHub

You can also set a theme in code by wrapping an existing Context with a ContextThemeWrapper which you could then use to inflate a layout etc.

The power of themes really comes from how you use them; you can build more flexible widgets by referencing theme attributes. Different themes provide concrete values at a later time. For example, you might wish to set a background color on a section of your view hierarchy:

1
2
3
4
5

<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<ViewGroup
android:background="?attr/colorSurface">

themes_vs_styles_theme_attr_usage.xml hosted with ❤ by GitHub

Rather than setting a static color (#ffffff or a @color resource) we can delegate to the theme by using the ?attr/themeAttributeName syntax. This syntax means: query the theme for the value of this semantic attribute. This level of indirection allows us to provide different behavior (e.g. providing a different background color in light and dark themes) without having to create multiple layouts or styles which are mostly identical but for a few color variations. It isolates the elements that are changing within the theme.

Use the ?attr/themeAttributeName syntax to query the theme for the value of this semantic attribute

Scope

A Theme is accessed as a property of a Context and can be obtained from any object which is or has a Context e.g. Activity, View or ViewGroup. These objects exist in a tree, where an Activity contains ViewGroups which contain Views etc. Specifying a theme at any level of this tree cascades to descendent nodes e.g. setting a theme on a ViewGroup applies to all the Views within it (in contrast to styles which only apply to a single view).

1
2
3
4
5
6
<!-- Copyright 2019 Google LLC.	
SPDX-License-Identifier: Apache-2.0 -->
<ViewGroup
android:theme="@style/Theme.App.SomeTheme">
<! - SomeTheme also applies to all child views. -->
</ViewGroup>

themes_vs_styles_theme_cascade.xml hosted with ❤ by GitHub

This can be extremely useful, say if you want a dark themed section of an otherwise light screen. Read more about this behavior here.

Note that this behavior only applies at layout inflation time. While Context offers a setTheme method, or Theme offers an applyStyle method, these need to be called before inflation. Setting a new theme or applying a style after inflation will not update existing views.

Separate Concerns

Understanding the different responsibilities and the interaction of styles and themes, helps to keep your styling resources more manageable.

For example, say you have a blue theme for your app, but some Pro screens get a fancy purple look and you want to provide dark themes with tweaked colors. If you tried to achieve this using only styles, you would have to create 4 styles for the permutations of Pro/non-Pro and light/dark. As styles are specific to a type of view (Button, Switch etc) you’d need to create these permutations for each view type in your app.

Exploding permutations of widgets/styles without theming

If instead we use styles and themes we can isolate the parts which alter by theme as theme attributes so we only need to define a single style per view type. For the above example we might define 4 themes which each provide different values for the colorPrimary theme attribute, which these styles then refer to and automatically reflect the correct value from the theme.

This approach might seem more complicated as you need to consider the interaction of styles and themes, but it has the benefit of isolating the parts that change per theme. So if your app rebrands from blue to orange, you only need to change this in a single place, not scattered throughout your styling. It also helps fight a proliferation of styles. Ideally you only have a small number of styles per view type. If you don’t take advantage of theming, it’s easy for your styles.xml file to get out of hand and explode with different variations of similar styles, which becomes a maintenance headache.

Join us in the next article where we explore some common theme attributes and how to create your own:

Android Styling: Common Theme AttributesIn the previous article in this series on Android styling, we looked at the difference between themes and styles and…medium.com

https://medium.com/androiddevelopers/android-styling-themes-vs-styles-ebe05f917578

Android多国语言文件夹汇总

Arabic, Egypt (ar-rEG) —————————–阿拉伯语,埃及
Arabic, Israel (ar-rIL) ——————————-阿拉伯语,以色列
Bulgarian, Bulgaria (bg-rBG) ———————保加利亚语,保加利亚
Catalan, Spain (ca-rES) —————————加泰隆语,西班牙
Czech, Czech Republic (cs-rCZ) —————–捷克语,捷克共和国
Danish, Denmark(da-rDK) ————————丹麦语,丹麦
German, Austria (de-rAT) ————————-德语,奥地利
German, Switzerland (de-rCH) ——————-德语,瑞士
German, Germany (de-rDE) ———————-德语,德国
German, Liechtenstein (de-rLI) ——————德语,列支敦士登的
Greek, Greece (el-rGR) —————————-希腊语,希腊
English, Australia (en-rAU) ————————-英语,澳大利亚
English, Canada (en-rCA) ————————–英语,加拿大
English, Britain (en-rGB) —————————-英语,英国
English, Ireland (en-rIE) —————————–英语,爱尔兰
English, India (en-rIN) ——————————–英语,印度
English, New Zealand (en-rNZ) ———————英语,新西兰
English, Singapore(en-rSG) ————————–英语,新加坡
English, US (en-rUS) ———————————–英语,美国
English, Zimbabwe (en-rZA) ————————–英语,津巴布韦
Spanish (es-rES) —————————————-西班牙
Spanish, US (es-rUS) ———————————–西班牙语,美国
Finnish, Finland (fi-rFI) ———————————芬兰语,芬兰
French, Belgium (fr-rBE) ——————————-法语,比利时
French, Canada (fr-rCA) ——————————-法语,加拿大
French, Switzerland (fr-rCH) ————————–法语,瑞士
French, France (fr-rFR) ——————————–法语,法国
Hebrew, Israel (he-rIL) ———————————希伯来语,以色列
Hindi, India (hi-rIN) ————————————-印地语,印度
Croatian, Croatia (hr-rHR) —————————-克罗地亚语,克罗地亚
Hungarian, Hungary (hu-rHU) ————————匈牙利语,匈牙利
Indonesian, Indonesia (id-rID) ————————印尼语,印尼
Italian, Switzerland (it-rCH) —————————-意大利语,瑞士
Italian, Italy (it-rIT) —————————————意大利语,意大利
Japanese (ja-rJP) —————————————-日语
Korean (ko-rKR) ——————————————朝鲜语
Lithuanian, Lithuania (lt-rLT) ————————–立陶宛语,立陶宛
Latvian, Latvia (lv-rLV) ———————————拉托维亚语,拉托维亚
Norwegian-Bokmol, Norway(nb-rNO) —————挪威语,挪威
Dutch, Belgium (nl-rBE) ——————————–荷兰语,比利时
Dutch, Netherlands (nl-rNL) —————————荷兰语,荷兰
Polish (pl-rPL) ——————————————-波兰
Portuguese, Brazil (pt-rBR) —————————葡萄牙语,巴西
Portuguese, Portugal (pt-rPT) ————————葡萄牙语,葡萄牙
Romanian, Romania (ro-rRO) ————————罗马尼亚语,罗马尼亚
Russian (ru-rRU) —————————————-俄语
Slovak, Slovakia (sk-rSK) ——————————斯洛伐克语,斯洛伐克
Slovenian, Slovenia (sl-rSI) —————————-斯洛文尼亚语,斯洛文尼亚
Serbian (sr-rRS) —————————————-塞尔维亚语
Swedish, Sweden (sv-rSE) —————————-瑞典语,瑞典
Thai, Thailand (th-rTH) ——————————–泰语,泰国
Tagalog, Philippines (tl-rPH) ————————–菲律宾语,菲律宾
Turkish, Turkey (tr-rTR) ——————————-土耳其语,土耳其
Ukrainian, Ukraine (uk-rUA) ————————–联合王国
Vietnamese, Vietnam (vi-rVN) ———————–越南语,越南
Chinese, PRC (zh-rCN)——————————–中文,中国
Chinese, Taiwan (zh-rTW)—————————–中文,台湾