一. Application Fundamentals
- 四大组件的声明:
(1)activity:
(2)service:
(3)broadcast receiver:
(4)content provider:
activity,service,content provider必须在manifest中声明系统才能调用,但是broadcast receiver也可以在代码中调用registerReceiver()方法来动态声明; - 四大组件的启动:
(1)activity:Intent:startActivity()、startActivityForResult()
(2)service:Intent:startService()、bindService()
(3)broadcast receiver:Intent:sendOrderedBroadcast()、sendStickyBroadcast()
(4)content provider:ContentResolver的query() - service使用显式intent比使用隐式更加安全,隐式不确定会把什么看不到的service启动起来;
- resources和代码分开的一大意义在于,可以为不同设备配置提供不同的resource,例如:切换语言,不同分辨率的手机;
二. App resources
资源外置化,且通过将文件名将资源文件分组,针对不同的设备配置,可以读取不同的文件下的资源。Android系统在运行时,根据当前配置获取合适的资源文件,系统会对不同文件在项目工程的R
文件(aapt工具自动生成)下生产资源ID,系统通过资源ID获取相应的资源。
(一)资源分组
- 在
assets
目录下的文件不会生成资源ID,所以必须使用AssetManager
来读取; - 资源分组:格式:
,其中config_qualifier可以是多个,中间用- -
分隔,但要注意,当有多个config_qualifier时,需要按照官网有顺序限制,否则系统无法识别会被认为是无效的资源; - 如果没有找到匹配系统设置的资源文件,则系统会使用默认的资源(不包含qualifier的资源集);
提供默认资源非常重要,原因有二:
- App可能在一个我们没有配置相应参数设置的手机上,如果没有默认配置,则会因为找不到资源而crash;
- Android的新版本有时会增加新的配置参数,可能会导致老的配置方式不支持,也会导致crash;
- 资源别名:当不同的配置需要同一个资源时,本办法是,在两个不同的资源目录下拷贝两份相同的资源;但更好的做法是,使用资源别名,即将资源在
res/drawable/
下拷贝一份如icon_
,然后分别两个资源目录下创建xml文件,如.png icon.xml
,并在该xml文件中用
指向icon_
。这样,只需要一份存储较大的png文件,和两份存储较小的xml文件,就可以做到上面的需求了。.png
- Drawable
@drawable/icon_ca
- Layout
(二)访问资源
在App中个,可以通过资源ID访问资源,资源ID都存放在工程的R文件中,R文件是由aapt工具在编译时自动生成的。每一类资源在R文件中都是一个子类,例如R.drawable
存放所有的drawable资源ID。虽然资源是由资源ID指定的,但我们不需要去R文件中寻找其ID值,因为资源ID总是由两部分组成:(1)资源类型,(2)资源名称;
- 从代码中访问:如
R.string.hello
,语法:
[.]R..
可以通过Context.getResource()
来获取资源;
- 从XML文件中访问:如
@string/hello
,语法:
@[:]/
注意:
- 当xml文件与R文件在同一个package时,可以忽略不写,但使用系统资源时,需要包括包名,如
android:textColor="@android:color/secondary_text_dark"
- 引用当前theme的style属性:如:
android:textColor="?android:textColorSecondary"
,语法:
?[:][/]
- 访问原始文件:
-
/assets
目录下:存放在/res
下的文件都需要通过资源ID来访问;因此,存放在/assets
下的文件无法通过R文件或者XML来访问其资源ID,而需要将其看做通常的文件系统,并通过AssetManager
来读取原始文件;eg:读取apk文件并安装内置插件; -
res/raw/
目录下:例如音频、视频文件等;可以通过openRawResource()
方法来读取byte流;
- 访问系统资源
例如,设置布局文件(在activity的oncreate方法中),系统theme主题(在AndroidManifest文件中)等;
(三)系统如何通过文件名匹配最match的资源
见官网
(四)处理配置变化
有时App可能会在运行时系统配置发生变化(例如:系统语言、横竖屏等),当配置发生变化时,Android系统会重新开启start(杀死进程,并重新启动),并在重启过程中自动重新load匹配的资源文件;我们需要做的是,在系统重启过程中,做好资源保存和重载的过程,可以使用onSaveInstanceState()
、ViewModel
、持久存储等方式:
- 更改配置时保留对象:系统自动重启进程,使用
onSaveInstanceState()
无法保存较大的对象,会使用大量内存并影响性能,推荐使用[ViewModel];(https://developer.android.com/topic/libraries/architecture/viewmodel) - 手动处理系统配置变化:有时,App由于特殊需求要避免重启操作,此时需要我们来手动处理系统配置变化,但这种方式不推荐,尽量使用第一种方式:
(1)在manifest中声明activity自己处理配置变化:
android:configChanges=""
(2)当声明的配置发生变化时,声明的activity会调用方法onConfigurationChanged(Configuration newConfig)
,并通过传递的Configuration对象来对新的配置做出相应的处理:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
(五) Localization
- 当在
/res
文件中有多种后缀符合设备配置时,大部分情况优先匹配语言; - 标记不需要翻译的部分:使用标签
- 全称是XML Localization Interchange File Format,中文名是XML本地化数据交换格式,用来标记不应翻译的消息部分;
- 属性id说明此占位符的用途,可任意命名
Visit us at http://my/app/home.html
- 在adb上设置Locale:主要用于在模拟器上测试,具体内容见官网
- pseudolocales测试App:(暂时没有见过使用的场景),具体内容见官网
- Unicode和国际化:Android支持使用 ICU library和CLDR project
来提供Unicode和国际化的支持,但使用该库时要分Android6.0(API23)以下和Android7.0(API24)以上来讨论,例如,具体介绍见官网
String skeleton = DateFormat.is24HourFormat(context) ? "Hm" : "hm";
String formattedTime = android.icu.text.DateFormat.getInstanceForSkeleton(skeleton, Locale.getDefault()).format(new Date());
- XML文件中的
标签:将复杂的xml资源inline
(六) 动画
- 分类:
(1)属性动画(Property Animation):通过Animation
类改变对象的属性值;
(2)视图动画(View Animation):分为两种:
-- 补间动画(Tween animations):通过Animation
类对单个图片执行一系列转换;
-- 帧动画(Frame animations):通过AnimationDrawable
类展示一系列图片; - 动画资源文件存放位置:
- 属性动画(Property Animation):在
res/animator/
,使用R.animator
类访问; - 补间动画(Tween animations):在
res/anim/
,使用R.anim
类访问; - 帧动画(Frame animations):在
res/drawable/
,使用R.drawable
类访问;
I. 属性动画(Property Animation)
- 位置:
res/animator/filename.xml
,使用资源ID来访问; - 获取资源:
(1)Java:R.animator.filename
(2)XML:@[package:]animator/filename
- 元素:
(ObjectAnimator)、
(AnimatorSet)、
(ValueAnimator) - 语法:
...
- 使用
(1)Java代码:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animator.property_animator);
set.setTarget(myObject);
set.start();
(2)XML文件:
android:stateListAnimator = "@[package:]animator/filename"
II. 补间动画(Tween animations)
- 位置:
res/anim/filename.xml
, 使用资源ID来访问; - 获取资源:
(1)Java:R.anim.filename
(2)XML:@[package:]anim/filename
- 元素:Animation
- 语法:
...
- 使用
ImageView image = (ImageView) findViewById(R.id.image);
Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
image.startAnimation(hyperspaceJump);
III. 帧动画(Frame animations)
- 位置:
res/drawable/filename.xml
,使用资源ID来访问; - 获取资源:
(1)Java:R.drawable.filename
(2)XML:@[package:]drawable.filename
- 元素:AnimationDrawable
- 语法:
- 使用
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = rocketImage.getBackground();
if (rocketAnimation instanceof Animatable) {
((Animatable)rocketAnimation).start();
}
动画总结
(七) Drawable
- Bitmap
(1)三种格式:.png
(preferred)、.jpg
(acceptable)、.gif
(discouraged);
(2)在编译过程中,aapt工具会使用无损图像压缩自动优化Bitmap文件,这样可以使该图片文件在同等质量的同时使用更少的内存;所以注意,如果在res/drawable/
下的图像文件的二进制码可能在编译器改变,如果想要通过读取bit流再转成bitmap文件,建议放在不会被优化的res/raw/
目录下;
(3)XML bitmap:
用作
的一个子元素可以用在state list
和layer list
中; - Layer list
LayerDrawable
是一个能够管理其他多个drawable的drawable对象。每个drawable(
)按照顺序在list
中绘制,顺序是:最后一个drawable在最上面;
- 通过drawable的当前level值来裁剪另一个drawable,可以通过gravity来控制裁剪方向,最常见的应用是实现自定义进度条;
(1)语法:
(2)自定义进度条:
-
-
持续更新中。。