安卓基础知识必备-青训营笔记

60 阅读8分钟

这是我参与「第四届青训营 」笔记创作活动的第1天

一、什么是程序

1、开发者的渠道image-20220727084601800

2、用户的角度image-20220727084643249

二、android的基础组件

1、界面组件(Activity)

1.1 、WHAT:界面容器

image-20220727085028646

1.2 、WHY:

  • 前台交互
  • 程序入口:就是响应用户的点击事件
  • 布局容器

1.3、生命周期:

  • onCreate():创建时回调,一般在此处创建视图和绑定数据
  • onStart():已启动,即将进入前台,但是此时还不可见,不可交互,可以在这里打点
  • onResume():与用户开始交互,位于Activity栈顶
  • onPause():Activity失去焦点或已暂停,Activity界面部分可见,下一个生命周期是onResume()或onStop(),比如上面是一个弹窗,下面的Activity就会处于onPause()
  • onStop():Activity不再可见,下一个回调是onRestart()或onDestory()
  • onRestart():重启已停止的Activity,下一个回调是onStart()
  • onDestory():销毁Activity,释放该Activity的所有资源
  • onSaveInstanceState():在非正常关闭时回调(系统回收界面),用于保存数据,不支持持久化数据
  • onRestoreInstanceState()/onCreate():用于恢复数据

image-20220727091650341

配置改变场景:

  1. 销毁:Resumed-onSaveInstanceState()-onPause()-onStop()-onDestroy()
  2. 重建:onCreate()-onStart()-onRestoreInstanceState()-onResume()

配置改变不重建Activity:Android Manifest中配置Activity节点的configChange属性

  • local:语言改变
  • fontScale:字体大小改变
  • orientation:旋转屏幕
  • keybordHidden:键盘显示隐藏

配置改变:onConfigurationChanged():通过设置configChange()属性就不会走onSaveInstanceState()和onRestoreInstanceState()方法,而是走这个回调方法

image-20220727093013934

  • 问题:在程序使用的时候,有电话打进来,这时程序会Crash(崩溃)

问题原因:页面被回收导致本地变量被置空

问题解决:

  1. 添加判空逻辑避免空指针的产生

  2. 在页面回收生命周期中存储数据,页面重建时进行恢复

    就是在onSaveInstanceState()写入需要保存的数据,在onRestoreInstanceState()进行数据恢复

1.4、启动模式(LauchMode)

问题引入:加入首页按钮后,点击会在当前页面栈加入新首页(这时就出现了两个首页,不应该出现两个首页),返回后首页会消失

预期:点击首页按钮回到首页,上面的页面全部退出image-20220727094444185

  1. standard:默认模式,允许重复image-20220727094555279
  2. singleTop:不允许连续重复,就是说位于栈的最顶的两个Activity不能是相同的,就是栈顶复用,当想要在栈顶重开一个和原本的栈顶Activity相同的Activity,如果是standard默认模式就会重新创建一个Activity,如果配置启动模式为singleTop,那就不会重新创建,而是回调onNewIntent()方法显示栈顶的Activityimage-20220727094711120
  3. singleTask:不允许栈内重复,就是说一个栈内不允许有多个相同的Activity,解决不允许有多个首页问题就是把LauchMode配置为singleTaskimage-20220727095446752
  4. singleInstance:整个系统不允许重复image-20220727095758828

总结:image-20220727095942963

2、界面组件:Fragment

2.1、WHY:

  • 解决碎片化的问题
  • 轻量,速度快:因为Activity的创建需要走IPC,而且还有一系列和Binder、Service、ActivityManageService相关的操作,比较耗时

2.2、基本用法:

  1. 创建Fragment布局文件

  2. 创建Fragment子类,加载布局文件

  3. Activity加载Fragment

    1. 静态加载:布局中绑定,就是在xml中绑定,把Fragment写到layout文件里面
    2. 动态加载:FragmentManager加载

image-20220727101500308

  • onAttach():Fragment和Activity建立关联时调用
  • onCreateView():Fragment创建视图时调用
  • onActivityCreated():Activity的onCreate()方法已返回时调用
  • onDestroy():当Fragment中的视图被移除时调用
  • onDetach():Fragment和Activity取消关联时调用
  1. 启动:onAttach()-onCreate()-onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed
  2. 退出:Resumed-onPause()-onStop()-onDestoryView()-onDestory()-onDetach()
  3. 部分覆盖:Resumed-onPause()-Paused
  4. 部分遮挡恢复:Paused-onResume()-Resumed
  5. 完全覆盖:Resumed-onPause()-onStop()-onDestroyView()
  6. 完全遮挡恢复:onCreateView()-onActivityCreated()-onStart()-onResume()-Resumed

注:Fragment生命周期可通过FragmentTransaction.setMaxLifecycle()手动干预,就是可以设置可走到的最长生命周期是哪一个,后面的就不会走到,不过用的比较少

2.3、Fragment与Activity的交互

组件获取:

  1. Fragment获取Activity中的组件:getActivity().findViewById(R.id.xxx)
  2. Activity获取Fragment中的组件:getFragmentManager.findFragmentById(R.id.fragment_xxx)

数据传递:

  1. Activity传数据给Fragment:setArgument(Bundle bundle):主要是在Activity初始化的时候传一些参数给Activity

  2. Fragment传数据给Activity:

    1. 通过对象直接传递(方法调用(getActivity().xxx()/接口调用)
    2. 异步方式:通过viewModel/handler/broadcast/evenBus等通信

总结:image-20220727103831370

3、服务组件Service

3.1、基本用法:

  1. 注册:AndroidManifest中使用<service.../>标签
  2. 创建:建立相应的Service实现类
  3. 加载:startService()/bindService(),启动服务后不需要与用户交互的比如下载就使用startService(),启动服务后需要与用户交互的比如音乐播放器就使用bindService()

3.2、生命周期:image-20220727105636196

  1. onStart():服务即将启动
  2. onBind():跟界面组件进行绑定
  3. onCreate():数据初始化
  4. onDestory():服务销毁

3.3、Service(与Activity通信)

  1. 定义Binder子类,并实现getService()方法,返回Service对象
  2. 实现Service子类onBind()方法,返回上述Binder对象
  3. 实例化ServiceConnection对象,实现onServiceConnected()方法,从中获取到Service实例
  4. Activity中调用bindService()方法,并传递步骤3的ServiceConnection对象,将流程跑起来
  5. Activity可以通过调用Service实例中的方法进行直接通信

4、广播组件(Broadcast)

用于一对多的消息通知,比如网络断开、连接,系统开关机,没电

4.1、基本用法:

静态广播:

  1. 注册:AndroidManifest中使用<receiver.../><intent-filter.../>
  2. 创建:建立相应的BroadcastReceiver实现类
  3. 接收:在步骤2类onReceive()中接收广播
  4. 发送:Context.sendBroadcast()

动态广播:

注册:Context.registerReceiver()

4.2、常用系统广播

Intent.ACTION_CONNECTIVITY_CHANGE//网络连接改变
Intent.ACTION_BATTERY_CHANGE//电量改变
Intent.ACTION_SCREEN_ON//开屏
Intent.ACTION_SCREEN_OFF//息屏
Intent.ACTION_PACKAGE_INSTALL//安装应用程序
Intent.ACTION_BOOT_COMPLETED//系统启动完成
Intent.ACTION_PACKAGE_ADDED//程序已安装
Intent.ACTION_PACKAGE_REPLACED//程序更新
Intent.ACTION_PACKAGE_REMOVED//程序卸载

广播需要权限配合设置

5、数据组件:ContentProvider

5.1、基本用法:

生产者:

  1. 注册:AndroidManifest中使用<provider.../>

    属性:authorities/exported/readPermission/writePermission

  2. 创建:建立相应ContentProvider实现类

    方法:onCreate/getType/insert/delete/update/query

消费者:

  1. 声明:AndroidManifest中声明权限

  2. 使用:context.getContentResolver()

    方法:insert/delete/update/query

6、Intent(意图)

1、Context.startActivity(Intent)

2、Context.startService(Intent)

3、Context.sendBroadcast(Intent)

eg:

image-20220727113731237

6.1、基本用法

  1. 显示Intent

    setComponent/setClass指定具体类

  2. 隐式Intent

    Action(动作)

    Data(数据)

    Category(类别)

    Type(数据类型)

    Component(组件)

    Extra(扩展信息)

    Flag(标志位):比如可以利用标志位来模拟启动模式中的singleTask和singleTop,但是保证不了singleInstance

6.2、系统能力image-20220727114645048

总结:image-20220727114705827

二、通信组件

1、线程间通信-Handler

1.1、基本用法:

  1. 创建:新建Handler,实现handleMessage(Meassage msg)
  2. 构造Message:what/setData()
  3. 发送:子线程调用Handler.sendMessage(Message)发送Message
  4. 处理:在Handler的handleMessage(Message msg)主线程更新UI

image-20220727115350395

2、进程间通信-Binder

image-20220727115626964

Binder数据拷贝次数少一点,效率高

2.1、为何不用共享内存

因为Linux的进程隔离,就是说进程1和进程2的内存空间是独立的,只能用内核空间image-20220727115948019

2.2基本用法:(CS结构)

服务端(Service):

  1. 定义一个AIDL文件
  2. 实现描述的接口,编写service
  3. 如果有实体类,需要提供实体类(jar包形式)

客户端(Client):

  1. 拿到AIDL文件
  2. 绑定服务,获得接口持有对象

image-20220727120902626

2.3、核心原理image-20220727120952408

eg:app的启动

image-20220727121232358

总结:image-20220727121509056

本课总结:image-20220727121546256

\