Android小知识
TextView 使用Html.fromHtml 的时候颜色建议用6位,目前不支持8位(无法改变颜色)
日期相关
G:年代标记符
y: 年(大小写区别 Y代表:Week year,标示这个周所属的年份;y标示才是我们日常使用的年)
M:月(大写表示月,小写表示分)
d:日(大写表示一年中的第几天,小写表示日)
H:时(24小时制的时间,小写:12小时制)
m: 分
s:秒
E:星期
D:一年中的第几天
w:一年中第几个星期
W:一月中第几个星期
a:上午或下午的标志符
k:一天中的第几个小时(24小时制)
K:一天中的第几个小时(12小时制)
z:时区
YYYY 和 yyyy 不一样:
以 2019年12月31日 举例:
yyyy-MM-dd :2019-12-31
YYYY-MM-dd :2020-12-31
参考:日期API
YYYY-MM-dd程序员,都加班的bug
数据库:
getReadableDatabase 不是以只读方式打开数据库,Android 中 getWritableDatabase() 和 getReadableDatabase() 方法都可以获取到 SQLiteDatabase 实例。
但getReadableDatabase()并不是以只读方式打开数据库,而是先执行getWritableDatabase(),失败的情况下才以只读方式打开数据库.
public synchronized SQLiteDatabase getReadableDatabase() {
// ...
try {
// 执行 getWritableDatabase() , 若出现异常,以只读方式打开数据库
return getWritableDatabase();
} catch (SQLiteException e) {
if (mName == null) throw e;
}
SQLiteDatabase db = null;
try {
// ...
// 以只读方式打开数据库
db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
// ...
mDatabase = db;
return mDatabase;
} finally {
// ...
}
}
``
##子线程未必不能更新UI
Android的UI访问时没有加锁的,多线程访问时并不安全。所以规定只能在UI线程中访问UI。负责检查线程的就是ViewRoomImpl的checkThread()方法
```java
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
然而ViewRootImpl的创建在onResume回调之后,那么onResume之前,子线程里也是可以更新UI的。即使ViewRootImpl创建后,只要不调用checkThread,子线程里更新也并不会报错。然而,不要在子线程更新ui
参考
代码new的View没有id
Android布局中通过@+id的方式,可以在R文案中生成对应的一个int值,用于运行时保证资源唯一性,但动态代码中的new的View 没有 id。
如果需要使用id,可以调用view的generateViewId方法生成id(API17+),而非用随机数产生或手写一个具体值。
View的getContext返回的未必是Activity
Activity中setContentView时一定是Activity
通过new View、View.inflate、LayoutInflater.inflate这几种方式添加View,我们传参时传的是什么context,view中就是什么Context
在5.0系统版本以下手机,且Activity是继承自AppCompatActivity的,那么View的getContext方法,返回的就不是Activity而是TintContextWrapper.
参考
RemoteViews和View没什么关系
RemoteViews提供了一组基础的操作用于跨进程更新,主要用于通知栏和桌面小部件的开发,感觉应该是一种远程View,其实不是:
public class RemoteViews implements Parcelable, Filter {
// ...
}
RemoteViews为跨进程操作控件提供的一系列方法的类。
boolean类型占用几个字节
Java规范数据类型文档没有精确定义内存中布尔变量的实际大小。
实际大小与虚拟机相关,可以肯定不是1个bit。
Java虚拟机的建议:
1、boolean类型被编译成int类型来使用,占4个byte
2、boolean类型被编译成byte数组类型,每个boolean数组站1个byte
参考
RecyclerView布局文件可指定layoutManager和spanCount
<declare-styleable name="RecyclerView">
<attr name="layoutManager" format="string" />
<attr name="android:orientation" />
<attr name="spanCount" format="integer"/>
<attr name="reverseLayout" format="boolean" />
<attr name="stackFromEnd" format="boolean" />
</declare-styleable>
在attr里可以指定layoutManager,spanCount,orientation。
9-patch图片是有padding的
NinePatchDrawable图形是一种可拉伸的位图,可制作视图的背景。Android会自动调整图形的大小以适应视图的内容。包含额外的1像素边框,必须使用9.png扩展名将其保存在项目的res/drawable目录下。
左,上:定义允许复制图片的哪些像素来拉伸图片
右,下:定义图片中允许放置视图内容的相对区域
因此,9-patch图片可能带有padding,如果控件没有明确设置,图片的padding会作为空间的padding。所以,有时候android:padding="0dp"该写还需要写的。
参考
硬件加速不是哪里都能开关
硬件加速是依赖GPU实现图形绘制加速。GPU引入不仅提高了绘制效率,还会由于绘制机制的改变,极大提高界面内容改变时的刷新效率。在Android4.0开始默认开启硬件加速,也可以手动控制打开关闭。
硬件加速在Window级智能开不能关;View级只能关不能开。
Application和Activity控制
在 AndroidManifest 文件中 Application 或 Activity 节点添加
android:hardwareAccelerated="true"
Window控制
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
View控制
view.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
查询是否开启硬件加速
View.isHardwareAccelerated()
Canvas.isHardwareAccelerated()
用getVisibility判断用户是否看见并不好
getVisibility()只判断它自身是否是显示状态。但是如果它的父级不可见呢?
用 isShown() 方法更合适些,会先判断当前 View 的flag, 然后循环拿到父View,判断是不是可见。只要有一个是不可见的,就返回false。
public boolean isShown() {
View current = this;
//noinspection ConstantConditions
do {
if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
ViewParent parent = current.mParent;
if (parent == null) {
return false; // We are not attached to the view root
}
if (!(parent instanceof View)) {
return true;
}
current = (View) parent;
} while (current != null);
return false;
}