Android 知识点

  • android.intent.category.DEFAULT的用途和使用

每一个通过 startActivity() 方法发出的隐式 Intent 都至少有一个 category,就是 “android.intent.category.DEFAULT”,所以只要是想接收一个隐式 Intent 的 Activity 都应该包括”android.intent.category.DEFAULT” category,不然将导致 Intent 匹配失败。一个 Intent 可以有多个 category,但至少会有一个,也是默认的一个 category。
只有 Intent 的所有 category 都匹配上,Activity 才会接收这个 Intent。
参考:https://www.jianshu.com/p/d7a88daffead

  • ConstraintLayout 种使用 include 时一定要设置 width 和 height 属性,否则 约束属性将不起作用
  • 在编译时集成 framework.jar, 使得编译通过, 在运行时加载系统的类

解决办法: 步骤1: 让系统提供 framework.jar, 然后在 module 里面,将 jar 放到 libs 目录下,在 build.gradle 中使用 compileOnly 的方式依赖 。build 时默认还是不会加载 framework.jar 中的类, 而是会加载系统的类,解决办法是调整 .idea/ .iml 中 android sdk 的顺序放到 加载 framework.jar 的后面,这样就会先加载framework.jar 了。

  • 用命令行打 jar 包
    http://t.zoukankan.com/liu-ke-p-4203638.html

  • 使用 Kotlin 调用 java 的方法必须要非常小心,例如 kotlin 调用 Java 返回 String 的方法,该方法有可能返回null,Kotlin 去接收返回值的时候,如果不是定义的可空变量,则会出现crash


//kotlin class
private fun format(str:String){
        val fmt1 = JavaMain.format(str)
        //上面一行虽然不会报错 但是调用 fmt1.length 会报错
        println(fmt1.length)

        //这里会报错, 因为返回的是null 但是接收的是 非空
        val fmt2:String = JavaMain.format(str)

        //这样是可以的
        val fmt3:String? = JavaMain.format(str)
    }


//java class 
public class JavaMain {
    public static  String format(String msg){
        return TextUtils.isEmpty(msg)? null:msg;
    }
}

  • Android Parcelable和Serializable区别

Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化

  • Navigation PopTo用法

们常见的一种逻辑如下: 有三个目标视图分别是A、B、C,有A到B,B到C,然后C到A。可以看到当我们倒C之后,后台堆栈当中包括A、B、C单个实例。当我们通过popUpTo A回到A的时候,意味着我们从堆栈当中把B和C删除了。当我们使用app:popUpToInclusive =“true”的时候,我们还会把A弹出堆栈并有效的清除它。如果我们没有使用app:popUpToInclusive =“true”那么也意味着我们的堆栈当中包含两个A的实例

  • Navigation
 

android:name 属性包含 NavHost 实现的类名称。
app:navGraph 属性将 NavHostFragment 与导航图相关联。导航图会在此 NavHostFragment
中指定用户可以导航到的所有目的地。
app:defaultNavHost="true" 属性确保您的 NavHostFragment 会拦截系统返回按钮。请注意,只能有一个默认 NavHost。
如果同一布局(例如,双窗格布局)中有多个宿主,请务必仅指定一个默认 NavHost

  • adb 获取系统硬件信息
 adb shell
 cat /proc/cmdline
  • 从 jsonobject 解析数据时,不推荐用 JSONObject.getString(),而是推荐用 JSONObject.optString(), 因为getString 时如果不存在该字段则会抛出异常,导致整个jsonobject解析出错,而 optString 不会抛异常,指挥该字段返回默认值而不影响其他字段的解析

  • 混淆方式
    1.只在 主 app module中开启混淆, 其他library 中关闭混淆,缺点是混淆和各组件拆分,不利于组件复用和移除

  1. library module 自身将 proguard-rule.pro 打包到 aar 中,并在 library 的build.gradle中添加配置
consumerProguardFiles "consumer-rules.pro"

较优方案是将通用的三方裤混淆梵高basemodule 中,每个module中独有的饮用裤的混淆放到
各自module中,最后在app的混淆文件中放入基础属性的混淆

  • System.getEnv 和 System.getProperty()

System.getenv()读取的是当前系统环境的环境变量,当不传入参数时,System.getenv()的返回值为一个只读的Map,其中包括当前环境下所有环境变量

  • data class

数据类必须有主构造函数,且至少有一个输入参数,因为它的属性字段要跟输入参数一一对应
主构造函数的输入参数前面必须添加关键字var 或者 val

  • kotlin 的内部类

kotlin 的内部类默认不能访问外部类的成员,如果想让 嵌套类 能访问外部类的成员,可以在嵌套类的 class 前面加上 inner 关键字,这样就变成了内部类, 内部类比嵌套类的好处是能访问外部类的成员,所以 kotlin 的内部,类就相当于 java 的嵌套,而 kotlin 的嵌套类则是加了访问限制

open class Bird(var name: String, val sex:Int = MAILE) {
    class Inner(var innerName:String){
         fun getName():String{
            //编译错误,报 Unresolved reference.
//            return "这是一只名字叫 ${name} 的鸟类 "
            return "这是一只名字叫 ${innerName} 的鸟类 "
        }
    }

  inner class InnerClass2(var innerName:String){
        fun getName():String{
            //编译错误,报 Unresolved reference.
            return "这是一只名字叫 ${name} 的鸟类 "
        }
    }
}

  • 为了解决 枚举类使用 when 表达式时,即便已经列出了所有的枚举类型,还是需要手动要加上 else 分支的问题, kotlin 提出了"密闭类"的概念,它更像一种严格的枚举类,它的内部仅有自身的实例对象,是一个有限的自身实例集合。
  • Koltin 的接口中允许在内部实现某个方法,而 Java 接口的所有方法都必须是抽象方法
  • Kotlin 构造函数默认参数

Kotlin 构造函数中的默认参数,在 java 代码中直接调用如果不传默认参数是会报错的,原因是 java 并没有直接支持默认参数,如果想让 java 也能识别构造函数的默认参数,需要加上 @JvmOverloads 注解

class AnimalDefault @JvmOverloads constructor(name:String, sex:Int = 0)

//Java 代码中调用

new AnimalDefault("jerry");
new AnimalDefault("jerry",1);

  • kotlin 把函数看成是一种特殊的变量,那么类在某种意义上算是一种特殊的函数

  • 尾递归函数

函数末尾的返回值重复调用了自身函数,成为尾递归函数,此时需要在 fun 前面加上关键字 trilrec,告诉编译器这是一个尾递归函数,则编译器会进行相应优化,从而提高程序性能

  • 内联函数

假如定义一个输入参数为 setArrayNumber(array:Array) 的参数,它并不接受 Array 或者 Array的入参数

private fun setArrayNum(array: Array){
        var result = "数组元素: "
        for (item in array){
            result = "$result$item"
        }
        println(result)
    }

如果想要让该函数同时接受 int 和 double 类型的数组,可以使用 reified 关键字

   private inline fun  setArrayNum2(array: Array){
        var result = "数组元素: "
        for (item in array){
            result = "$result$item"
        }
        println(result)
    }
  • Kotlin 的函数是一定存在返回值的, 即便开法则不声明任何返回参数,kotlin 函数也会默认返回一个 Unit 类型的对象

  • Kotlin 判断内容(结构)相等用的是 “==”,判断饮用相等用的是"==="

  • Kotlin 相比 java 强大之处:扩展函数,默认承诺书,接口委托,属性代理等 java 不具备的高级特性

  • “javac”的作用是将java源文件编译为class文件(即自解码文件);“java”命令的作用是运行class文件。

  • 修改 cmake 版本

image.png
  • lint 检查

命令行输入

./gradlew lint 

您应看到类似于以下内容的输出:

> Task :app:lint
Ran lint on variant release: 5 issues found
Ran lint on variant debug: 5 issues found
Wrote HTML report to file:/app/build/reports/lint-results.html
Wrote XML report to file:/app/build/reports/lint-results.xml
  • 热修复不能修复 主 dex的包,只能修复非 主 dex 中的包
  • 对list进行 for循环遍历时一定要记得先判断,否则会报空指针


    image.png
  • adb remount

将设备改为可读可写

  • 修改Textview的 maxLenght 可以达到 文字是按两行还是三行展示
  • 使用kotlin定义接口时,接口方法中的参数定义成非空类型,调用的时候穿了null导致崩溃了,坑
![image.png](https://upload-images.jianshu.io/upload_images/6280690-451f7dd3529ebade.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  • 使用 Sqlite首次查询时,不管是查询 1 条数据还是几千条数据,可能都需要 200 ms左右, 这是 Sqlite的局限性。

  • Bitmap 缩放后 用Paint draw出来,Paint是有设置抗锯齿的,但是看到还是有锯齿,解决办法是给canvas设置


  • 平板横竖屏切换的时候发现无法切换成功,但是其他平板上的其他应用又是可以切换成功的

定位思路:自己写一个demo去验证看看有没有问题, 如果没有问题再看启动Activity的堆栈情况,看看启动的M艾诺Actiivyt有没有做什么特殊的操作

  • 横竖屏切换后发现界面显示异常,横屏的显示出了竖屏的效果

也是写个全新的demo来试验,然后切换横竖屏后看下autoSize 获取到的宽高值是多少,是不是获取错误了

  • Navigation 使用 Directions 跳转
一 添加依赖
1. 添加 safeArgs 依赖
项目根 build.gradle
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"

2.module 的 build.gradle

apply plugin: "androidx.navigation.safeargs.kotlin"

二  build 后会生成自动生成 NavFragment1Directions 和
  • android studio 查看 kotlin字节码

Tools -> Kotlin -> show Kotlin byte code -> Decompile

  • Fragment中有一个 view 属性返回的是 fragment的根布局,因此没必要自己再定义一个 rootView来缓存
  • android studio 分析代码
image.png
  • 官方为什么推荐使用 SparseArray 取代 HashMap

HashMap: 使用一个默认容量为16的数组来存储数据,HashMap内部存储结构是使用哈希表的拉链结构(数组+链表).,当达到一定的容量限制时(这个容量满足这样的一个关系时候将会扩容:HashMap中的数据量>容量*加载因子,而HashMap中默认的加载因子是0.75),HashMap的空间将会扩大,而且扩大后新的空间一定是原来的2倍,所以,重点就是这个,只要一满足扩容条件,HashMap的空间将会以2倍的规律进行增大。假如我们有几十万、几百万条数据,那么HashMap要存储完这些数据将要不断的扩容,而且在此过程中也需要不断的做hash运算,这将对我们的内存空间造成很大消耗和浪费,而且HashMap获取数据是通过遍历Entry[]数组来得到对应的元素,在数据量很大时候会比较慢。
SparseArray:比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,为了优化性能,它内部对数据还采取了压缩的方式来表示稀疏数组的数据,从而节约内存空间
参考:https://blog.csdn.net/woshizisezise/article/details/79361458
https://www.cnblogs.com/zly1022/p/7743466.html

image.png
  • ViewPropertyAnimator 和 ObjectAnimator 的区别是 前者只能是对view给定的属性做动画,后者可以自定义属性来做动画

  • ObjectAnimator 使用方式

1.给自定义View 添加 set/get方法
2.ObjectAnimator.ofXXX()
3.ObjectAnimator.start()

  • Kotlin 的 object 关键字

object 是 java的替代品之一,只是不用像 Java 一样给每个字段和方法都加上 static,当然我们也没有其他选择,当一个类加上了object关键字,所有的方法和字段都相当于是加上了 static,因为其本质上是个单例对象,当我们希望某个类不是单例,但是却希望其有静态的变量和方法,就可以用 companion object

  • Kotlin lambda

函数 :: 就变成了对象,一个函数类型的对象,kotlin 中函数可以作为参数传递的本质是:函数可以作为对象存在。双冒号的写法叫做函数引用,加了双冒号就变成了对象,但 Kotlin 的函数的本身性质又决定了它没办法被当做是一个对象,kotlin

  • ImgeView 的 adjustViewBounds 属性

调整ImageView的边界,使得ImageView和图片有一样的长宽比例。adjustViewBounds只有在ImageView一边固定,一边为wrap_content的时候才有意义。设置为true的时候,可以让ImageView的比例和原始图片一样,以达到让图片充满的ImageView的效果。

  • overridePendingTransition(0,0); 传 (0,0)会使界面跳转没有动画
  • 不要使用 onClickWithDeboucing来做按钮点击防抖(有时候会无法响应事件)
  • 不要使用 OvservableField来刷新页面,其防抖特性可能导致某些情况下界面不刷新
  • 不要用Livedata 来监听数据做界面跳转,因为有可能会出现多次跳转的情况
  • RecycleView itemDecoration
image.png
  • ViewPage 切换item时设置不用展示动画,

viewpager.setCurrentItem 第二个参数传 false

viewpager.setCurrentItem(position, false);
  • Recycleview 用 GridLayoutManager时内容无法居中, 原因是 adatpe 的layout 根布局的宽度不是用的match_parent


    image.png
  • 干掉 Kotlin 的 todo 函数


    image.png

使用 ViewPage + +TabLayout + FragmentPageState 时 , 更新了 TabItem但是对应的Fragment 没有刷新,原因是
FragmentStateAdapter 返回的 getItemId, 返回的是 postion 的值,导致不会走 createFragment

  @Override
    public long getItemId(int position) {
        try {
            String result = mIdList.get(position);
            if (TextUtils.isEmpty(result)) {
                result = "" + getGrade() + position;
                mIdList.put(position, result);
            }
            return Integer.parseInt(result);
        } catch (Exception e) {
            return super.getItemId(position);
        }
    }
image.png
!mFragments.containsKey(itemId)  的条件为 false 导致不会走 creaeFragment 重建 

  • 给 Textview 设置样式
Textview.setTextAppearance(@StyleRes int resId) 
  • 对某个对象执行 copy 方法时,发现返回的对象为空,给类加上实现 Serializable 接口就可以了
public static abstract class ICallback implements Serializable {
      public ICallback copy() {
         ByteArrayOutputStream bao = new ByteArrayOutputStream();
         ObjectOutputStream oos;
         Object obj = null;
         try {
            oos = new ObjectOutputStream(bao);
            oos.writeObject(this);
            oos.close();
            ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            obj = ois.readObject();
            ois.close();
         } catch (Exception e) {
            e.printStackTrace();
         }
         return (ICallback) obj;
      }
   }
  • Kotlin 类实现某个接口时,会自动在每个接口方法内部自动加上
TODO("Not yet implemented")

必须手动删除这行代码否则程序运行会报错,解决办法是在 studio 的 code template中删除

image.png
  • Activity 启动模式

默认启动规则
在不同的Task中打开同一个Activity,Activity会被创建同一个实例,分别放进每一个task, 例如在短信应用中,点击一个电话号码,选择 "添加联系人",会跳转到 通讯录 的 "添加联系人"界面,此时按返回键,会回到短信的界面,此时按最近任务键,看到的是短信的task,而不是通讯录的task。此时回到桌面,点开桌面上的通讯录图标,看到的应该是通讯录列表界面,而不是刚刚打开的添加联系人界面,因为用户的这个操作,大概率是要查看通讯录列表界面。相反,此时切回短信App,应该回到的是添加联系人界面,继续编辑联系人信息,所以对于添加联系人信息页面来说,它是和打开它的那个App有相关性,而不是提供它的app。在不同的Task中打开同一个Activity,activity会被创建多个实例分别放进每一个Task,互不干扰。
但是如果是在短信应用中点击邮箱链接,在最近任务中,用户会希望看到邮箱的task出现在短信task的旁边, 在桌面点击邮箱图标时,也希望回到的是写邮件的界面。两个不同的场景应该有不同的效果, 要想实现这种效果,将邮箱的activity设置成singletask就行了,singletask可

  • 在onCreate中执行handle.post的消息需要等到 执行了onResume方法才会执行
  • 给ScrollView 内部的 LinerLayout 设置weight属性发现没有效果,解决办法是在 ScrollView中设置 android:fillViewport="true"
  • 在Kotlin中@JvmOverloads注解的作用就是:在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
    在 Kotlin 中调用默认参数值的方法或者构造函数是完全没问题的,但是在 Java 代码调用相应 Kotlin 代码却不行,也就是,Java 代码不能调用在 Kotlin 中使用默认值实现的重载函数或构造函数。
    @JvmOverloads 就是解决这一问题的
  • IdelHandler的坑

当主线程不忙碌(当前MessageQueue中没有message 或者有message 但是还没到执行时间)的时候会执行IdleHandler里面的任务,但是以下场景下不管多久 idleHandler永远不会被执行
1.在 View 的 onDraw 方法里面无限制的直接或者间接调用 View 的 invalidate 方法
2.做一个无限循环的View 动画

  • kontlin-android-extension存在的目的是为了不用finviewbyid,直接在视图中使用xml定义的view,后面被遗弃掉,原因是在adapter中使用这种方式,编译成java字节码后发现每次都findviewByid,导致viewholder的复用机智失败了,官方推荐用viewbinding替代kotlin-android-extension

  • RecycleView 设置 GridLayoutMananger 时,item无法居中显示,原因是 item 的xml布局的根布局参数写的是wrapContent 或者是具体的dp数值,而在GridLayoutManager设置的时候是需要设置每行显示的数目的,而这个设置就规定了每个布局的大小。所以,这两者产生了冲突(参考:https://blog.csdn.net/hacker_crazy/article/details/78478890)

  • 任务管理器快捷键:ctrl + alt +delete
  • 运行项目,报错解决办法:

jdk 配置


image.png

不能使用

image.png
  • 无线调试

adb tcpip 5555

  • ctrl + shift +esc: 强制关闭任务
  • android studio 无线调试


    image.png
  • 一欧项目配置了 ssh key,但是用studio 自带的git界面管理工具无法拉取和提交代码(用命令行可以),报
nvocation failed Unexpected end of file from server java.lang.RuntimeException: Invocation failed U

解决办法参考: https://www.codenong.com/cs105319883/


  • git 设置用户名和邮箱

设置全局
git config --global user.name jerry
git config --global user.email [email protected]
设置单独项目
git config user.name jerry
git config user.email [email protected]
查看配置的用户名和邮箱
git config --list

  • Mac 命令行执行 ./gradlew build 报错
zsh: permission denied: ./gradlew

解决办法:在命令行执行, 增加权限就可以了

sudo chmod -R 777

  • 查看 ip 地址

Mac :ifconfig Windows:ipconfig

  • windows 配置了 gradle_home 环境变量,在命令行输入明亮发现无效,重启电脑就可以了
  • cd ~/ 回到系统用户目录
  • 激活和注销 tasks

task 的 enable 属性可以控制 task 是否生效,当设置为 false,执行task时,它不会做任何动作

task ex15_22{
    doLast {
        println 'ex15_22 run'
    }
}

ex15_22.enabled = false
  • 儿童教育的 gp_login 中,用kotlin代码定义了 一个 ContentProvider,并且在清单文件中声明了,运行的时候报错,如下


原因是使用了 Kotlin 代码, 但是没有在 build.gradle 中申明引用 Kotlin 的插件

apply plugin: 'kotlin-android'

  • ./gradlew app:dependencies. 可以查看库依赖列表

  • mkdir -p src/main/java : 新建 src/main/java 目录

  • ./gradlew tasks 可以查看所有的task

  • 安装 gradle
    1 . 在gradle 官网(https://gradle.org/install)下载 gradle 版本,放到本地文件夹,例如放到
    =/Users/jerry/work/gradle/gradle-7.3

    1. 在.bash_profile 中配置环境变量
GRADLE_HOME=/Users/jerry/work/gradle/gradle-7.3
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin

3 命令行输入 「gradle」 测试是否安装成功

  • 在 build.gradle中想要能加载 gradle 源码,需要在 buildSrc的build.gradle中添加

dependencies {
    //依赖gradle 源码
  implementation gradleApi()
    implementation 'com.android.tools.build:gradle:4.0.2'
}
  • command + shift + 3: 截取全屏, command + shift + 4: 截取部分屏幕

  • Android笔记之Fragment中创建ViewModel的正确方式

  • ViewPage的Fragment中创建ViewModel需要采用get(String key, Class clz)的方式来创建,否则旋转屏幕后Fragment中的ViewModel为新建的,不会保存activity销毁前的数据

  • 如果是aar,那么需要主工程手动添加该 aar 的依赖库,因为aar 本身是没有下载依赖库的,所以需要主工程手动添加依赖

  • 如果主module(app module) 和 library 中的style名字相同,则主module中的style 会覆盖library中的style

  • AS 中,选中代码 -> 右键 -> Copy/paster special -> Copy reference 可以拷贝完整的 "包名+类名+方法名"
    , 例如拷贝 MainActivity的bindView方法,将会得到

com.apache.fastandroid.MainActivity#bindView
  • Camera 旋转的图形默认是歪的(不对称的),因为Camera默认是以原点为中心,而不是以图片的中心点来旋转的,但是 Camera 又没有提供设置轴心的方法,因此只能在旋转前先平移,旋转完之后再挪回来
  • canvas 的几何变换内部使用的 是 Matrix类 , 但是 Matrix 能做的比 Canvas 更多一些,例如
  1. canvas的几何变换顺序是反的, Matrix 是可以自定义顺序的, 例如 Matrix.preTranslate 为往前面插入平移,postTranslate 为往后面插入平移。 2. Matrix 能实现所有的几何变换,而不限于常见的几个 tranlate,rotate等
  • canvas 的几何变换是可以叠加使用的,但是有一点需要注意,它的几何变化顺序是倒序的,也就是说如果想要先移动再旋转,需要写成

canvas.rotate()
canvas.translate

  • git分布式特点

a:没网也可以提交,可以分多个commit ,集中式仓库就做不到这一点(必须整体提交,一次提交几千上万行代码不利于后面的代码审核 )
2.git clone xxxx git-demo2 克隆到本地的git-demo2 目录

  • Databinding 报错排除

在 Android Studio 的 Terminal 中,输入 gradlew build(MacOS 下 ./gradlew build),通过这个来编译,就能精准地打印出问题所在。屡试不爽!

  • ObservableField 和 LiveData 都可以在databinding中使用,那它俩选择哪个比较好呢?

其实它俩各有各的特点,ObservableField 的特点是支持防抖,在 set 的数据不变的情况下,
可以避免不必要的重复绘制。LiveData 则没有防抖的特性。所以可以根据场合来选择合适的方案。

  • mkdir -p src/main/java : 创建 src/main/java 目录

  • 看手机cpu型号
    先adb shell, 然后cat /proc/cpuinfo


    image.png
  • Random.nextBytes(byte[] bytes) 方法用于生成随机字节并将其置于用户提供的字节数组

  • adb install/uninstall path: 安装/卸载 apk
    -l: 锁定该程序
    -r:替换原有的apk安装
    -s:安装s卡内,而不是设备内部存储
    -k:不删除程序所运行所产生的数据和缓存目录

  • adb shell screencap filename:截屏

  • adb shell screenrecord[options] filename:录制视频

  • adb shell dumpsys[option]: 获取cpu呢困/cpu/wifi等系统信息

aop编程

  • APT: source Code -> .java文件的过程中做处理,例如ButterKnife,ARouter
  • AspectJ: .java ->.class文件转换的过程中做处理,
  • Javaassit: .class -> .dex 文件转换的过程中做处理

临时

  • tcp的三次握手
1.第1次握手:建立连接,客户端发送连接请求报文段,把标有SYN的数据包发送给服务端
2.第2次握手:服务端接收到客户端的SYN报文段,同时发送标有SYN/ACK的数据包
3.第3次握手:客户端收到服务端的SYN/ACK的数据包后,向服务端发送标有ACK的数据包

HTTP

  • tcp的3次握手
1.第1次握手:建立连接,客户端发送连接请求报文段,把标有SYN(建立连接)的数据包发送给服务端(客户端发送信息:服务端知道了 客户端的发送信息能力和 服务端自身的接收能力是没有问题的)
2.第2次握手:服务端接收到客户端的SYN报文段,同时发送标有SYN/ACK(ACK代表确认)的数据包(服务端发送信息:客户端知道了 服务端的发送信息能力和 客户端的接收能力是没有问题的)
3.第3次握手:客户端收到服务端的SYN/ACK的数据包后,向服务端发送标有ACK的数据包(客户端发送信息:服务器收到信息,确认了服务端自身的发送能力是没有问题的)

至此通过tcp的3次握手,客户端和服务端都确定了自身的发送信息和接收信息能力是没有问题的
  • tcp的 4次挥手
1.第1次挥手:客户端向服务端发送(FIN=1:关闭) 报文段,客户端进入 FIN_WAIT状态,表示客户端没有数据需要发送给服务端了。
2.第2次挥手:服务端收到客户端发送的FIN报文段,向客户端回了一个ACK报文段。
3.第3次挥手:服务端向客户端发送FIN报文段,请求关闭连接,同时服务端进入
LAST_ACK 状态。
4.第4次挥手:客户端收到服务端发送的FIN报文段后,向服务端发送ACK报文段,然后客户端进入TIMER_WAIT状态。服务端收到客户端的ACK报文后,就关闭连接,此时客户端等待2MSL(指一个片段在网络中最大的存活时间)后依然没有收到回复,则说明服务端已经正常关闭,这样客户端就可以关闭连接了。
  • 查看data/data

android studio右下角的Device File Explore


image.png
  • 如果bean的字段和服务器返回的字段名称不一致,在用gson序列化的时候,可以采用Serializable注解

@SerializedName("person_name") String name;
@SerializedName("person_age") String age;
@SerializedName("person_sex") String sex;

. 反射

.注解

.apt

常用Element子类

TypeElement:类
ExecutableElement:成员方法
VariableElement:成员变量
通过包名和类名获取TypeName
TypeName targetClassName = ClassName.get(“PackageName”, “ClassName”);
通过Element获取TypeName
TypeName type = TypeName.get(element.asType());
获取TypeElement的包名
String packageName = processingEnv.getElementUtils().getPackageOf(type).getQualifiedName().toString();
获取TypeElement的所有成员变量和成员方法
List members = processingEnv.getElementUtils().getAllMembers(typeElement);

零碎知识点

  • adb修改系统时间:
    date -s “20180902.144100”
  • 获取imageview的大小




@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (DEBUG) {
            // 在 debug 模式下绘制出 drawable 的尺寸信息
            Drawable drawable = getDrawable();
            if (drawable != null) {
              
                Rect bounds = drawable.getBounds();
                Log.d(TAG, "onDraw width:"+bounds.width() +", height:"+ bounds.height()
            }
        }
    }
  • 自定义View之 padding,margin处理

当我们使用系统自带的控件时,margin和padding都是生效的,因为系统已经帮我们处理好了,但是当我们自定义View时,如果不单独处理,那么系统是不会识别,不生效的

你可能感兴趣的:(Android 知识点)