Android小知识

2020-01-13  本文已影响0人  主音King

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;
}
上一篇下一篇

猜你喜欢

热点阅读