Android 随心笔记(更新至2021.07.05)

Posted 小柴的回忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 随心笔记(更新至2021.07.05)相关的知识,希望对你有一定的参考价值。

笔记


小柴的笔记

笔记都是零碎的笔记,请先在右边目录查看是否有自己需要的内容,也可以向笔者提供自己觉得重要,觉得好的笔记。谢谢观看

面向对象的三大特征

  • 多态
  • 封装
  • 继承

面向对象的五大基本原则

  • 单一职责原则
  • 开放封闭原则
  • 里氏替换原则
  • 接口隔离原则
  • 依赖倒置原则

Activity的生命周期

生命周期有7个,分别是:
onCreate()、onStart()、onResume()、onPause、onStop()、onDestory()

启动Activity:onCreate() → onStart() → onResume() → 点击home键退出Activity →onPause() → onStop() 再重新进入Activity → onRestart() → onStart() → onResmue()

启动Activity:
FirstActivity:onCreate() →
FirstActivity:onStart() →
FirstActivity:onResume() →
FirstActivity:onPause() →
切换第二个Activity →
SecondActivity:onCreate() →
SecondActivity:onStart() →
SecondActivity:onResume() →
SecondActivity:onPause() →
返回第一个Activity →
FirstActivity:onRestart() →
FirstActivity:onStart() →
FirstActivity:onResmue() →
SecondActivity:onStop() →
SecondActivity: onDestory()

Activity启动模式

  • standard 默认模式:每创建一个Activity都回向栈中加入一个Activity
  • singleTop 栈顶模式:只要栈顶的Activity是我们需要创建的Activity,那就会直接复用栈顶的Activity使用
  • singleTask 栈中复用模式:只要栈中存在Activity是我们需要创建的Activity,将上面的Activity弹出,并那就将该Activity置顶.
  • singleInstance 单例模式:创建一个新的栈(Task),只用于存放该Activity

android 常用的设计模式

  • 单例模式
  • 建造者模式(Build模式)
  • 观察者模式 (EventBus为观察者模式)
  • 适配器模式
  • 代理模式
  • 工厂模式
  • 策略者模式

单例模式

确保某一个类的实例对象只有一个,且此类的实例对象供整个程序使用。这是笔者任务较好的单例模式

public class Test{
	private static Test instance = null;
	private Context mContext;
	//构造函数
	private Test(Context context){
		mContext = context
	}
	/**
	 * 为何要两次判断呢,因为如果只有第一次的话,可能会出现多个线程同时调用方法,
	 * 导致同时创建多个单例实例。而只有第二次的话,创建之后每次使用单例都得多线程等待,导致浪费时间。
	 * 所以,当多个线程同时调用,但却没有单例时,排队一个一个进入线程同步,这样第一个进入时没单例,
	 * 就创建单例,第二个进入的时候,判断已经有单例,就创建单例。
	 */
	public static Test newInstance(Context context){
		context = context.getApplicationContext();
		if(instance == null){ //先判断是否存在单例
			synchronized(Test.class){//存在单例的时候,在通过同步锁锁住
				if(instance == null){//进入同步锁后,再次判断是否存在单例,不存在就新建单例
					instance = new Test(context);
				}
			}
		}
		return instance;
	}
}

建造者模式(Build模式)

将一个复杂对象的构造与表示分离,使同样的构建过程可以创建不同的表示
而最经典的建造者模式的使用就是我们经常使用的Dialog对话框
使用builder内部类对象的.setIcon方法设置图标,setTitle方法设置标题等等,最后使用.create()方法创建一个AlerDialog对象,通过AlerDialog.show方法显示对话框

public void setDialog(){
        AlertDialog.Builder builder= new AlertDialog.Builder(this);
        AlertDialog dialog = builder
                .setIcon(R.drawable.chai)//我是图标
                .setTitle("我是标题")
                .setMessage("我是提示信息")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(DialogActivity.this, "你选择了确定", Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(DialogActivity.this, "你选择了取消", Toast.LENGTH_SHORT).show();
                    }
                })
                .create();
        dialog.show();
}
        

匿名类

接口是不能被new实例化的,所以我要在内部重写需要的接口方法,这样就可以new出一个实现接口方法的对象,但因为这个对象的类名不可见,所以被叫做匿名类

//比如Service的的IBinder接口
IBinder mIBinder = new IBinder(){
	//重写的方法
};

handler的使用,主线程向子线程发送信息

不能立即发送mHandler,因为handler在子线程创建实例,主线程运行发送信息的时候,他不一定创建完成。

private Handler mHandler;

	new Thread(new Runnable(){
		@Override
		public void run(){
			Looper.prepare();
			mHandler = new Handler(){
				@Override
				public void handleMessage(@NonNull Message msg){
					super.handleMessage(msg);
					switch(msg.what){
						case 0x02:
							Log.d("Memory", "0x01:" + msg.arg1);
					}
				}
			};
			Looper.loop();
		}
	}).start();
	//不能立即发送mHandler,因为handler在子线程创建实例,主线程运行发送信息的时候,他不一定创建完成。
	Message msg = Message.obtaion();
	msg.what = 0x02;
	msg.arg1 = 123456;
	mHandler.sendMessage(msg);

ANR

ANR是应用无响应的
在主线程超过5秒、广播超过10秒、服务超过20秒
后台广播超过60秒、后台服务超过200秒、内容提供者超过10秒
的延时操作时,应用就会报ANR应用无响应
处理方法很明确,不要做超过规定时间的延时操作
具体方法如下

  • UI线程尽量只做更新UI的事
  • 使用子线程处理IO操作、数据库操作、连接网络等有可能延时的操作
  • 若广播需要做延时操作,在IntentService线程进行延时操作

泛型类与泛型方法

  • 泛型类是在实例化类的时候指明泛型的具体类型
  • 泛型方法是在调用方法的时候指明泛型的具体类型
  • 泛型方法在泛型类中有以下两种情况:
  1. 泛型方法的泛型T 是一个全新的泛型 和类中的泛型T可以是相同类型,也可以是不同的任意类型
  2. 泛型方法的泛型A和类中的泛型A 可以是相同类型,也可以是不同的任意类型,即便没有在类中生声明,也能正常识
class MyClass<T> {
	public <T> void method1(T t){
		...
	}
	public <A> void method2(A a){
		...
	}
}

大佬文章点这里

可变参数

意思就是运行定义多个参数。
如下的属性动画ValueAnimator的源码,参数就是可变参数,可以多个int值

public static ValueAnimator ofInt(int... values) {
    ValueAnimator anim = new ValueAnimator();
    anim.setIntValues(values);
    return anim;
}
ValueAnimator valueAnimator = ValueAnimator.ofInt(10100101001010010);
ValueAnimator valueAnimator = ValueAnimator.ofInt(101005030);

RecyclerView、ViewHolder、Adapter的关系

  • RecyclerView的工作是回收和定位屏幕上的View
  • ViewHolder的工作是容纳View视图
  • Adapter用于创建必要的ViewHolder,绑定ViewHolder至模型层数据
    RecyclerView需要视图对象的时候,会去找Adapter,Adapter返回数据给RecyclerView

Android系统架构(五层)

  1. 应用层
  2. 应用框架层
  3. 系统运行库层
  4. 硬件抽象层
  5. Linux内核层

应用层

系统内置的应用程序以及非系统级的应用程序都属于应用层。负责与用户进行直接交互。有Java、Kotlin、Flutter三种开发方式。

应用框架层

应用框架层为开发人员提供了可以开发应用所需要的API,我们平常开发应用程序都是调用这一层所提供的API开发,也包括系统的应用。
使用Java编写,被称为Java Framework

系统运行库层

又分为两个库:C/C++程序库和Android运行时库

硬件抽象层

位于操作系统内核与硬件电路之间的接口层,硬件抽象化,保护硬件厂商的知识产权,隐藏特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可以再多种平台上进行移植。简单来说:就是将控制硬件的动作存放在硬件抽象层

Linux内核层

Android的核心系统服务基于Linux内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。

Android系统启动流程

刘望舒的Android系统启动流程

  1. 启动电源以及系统启动,引导程序Bootloader,Linux内核启动
  2. 启动init进程(第一个进程)

创建一些文件夹并挂载设备
初始化和启动属性服务
解析init.rc配置文件并启动zygote进程

  1. 启动zygote进程

创建AppRuntime并调用其start方法,启动Zygote进程。
创建DVM并为DVM注册JNI
通过JNI调用ZygoteLnit的main函数进入Zygote的Java框架层
通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用进程
启动SystemService进程

  1. 启动SystemService进程

启动Binder线程池,用于和其他进程通信
创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理
启动各种系统服务

  1. 启动Launcher 应用程序

启动SystemService进程后,会启动PackageManagerService,PackageManagerService启动后将系统种的应用安装完成。在此前以及启动ActivityManagerService会启动Launcher
ActivityManagerService的systemReady()函数启动Launcher
启动Launcher后将已安装的应用的快捷图标显示到界面上

AMS的启动流程

AMS的启动是再SystemService进程种启动的

  • 通过SystemService的main()函数中调用SystemService().run()函数
  • 通过SystemService.run()函数中的startBootstrapServices()函数中调用的(AMS属于引导服务)
  • 调用mActivityManagerService = mSystemServiceManager.startService(
    ActivityManagerService.Lifecycle.class).getService();//1获取AMS
  • 在startService()中通过反射来创建Lifecycle的实例,同时得到Lifecycle的构造器constructor,
  • 在startService()中 service = constructor.newInstance(mContext) 来创建Lifecycle类型的service对象。
  • 将创建的service添加到mService对象列表中注册
  • service.onStart()启动service
  • 在创建Lifecycle对象时,它的构造方法中已经创建了AMS对象 AcitivitManagerService mService = new ActivityManagerService(context)
  • Lifecycle的onStart()里面就是 mService.start() 启动AMS
  • Lifecycle的getService()里面就是 return mService 返回AMS
    (所以第三条的startService传入的时Lifecycle.class,最后getService()获取AMS)

AMS的作用

AMS是系统核心服务,主要用于处理系统中四大组件的启动、切换、调度以及应用进程的管理和调度等工作

AMS 和 AM的关系

ActivityManager,主要用于对运行中的Activity进行管理,但管理工作是由AMS处理的。
因为AMS作为系统核心服务,不能暴露很多API给ActivityManager。
所以ActivityManager通过ActivityManagerNative(AMN)类的getDefault方法获取ActivityManagerProxy(AMP),然后通过AMP,和AMN通信,又因为AMS是AMN抽象类的子类,所以ActivityManger可以通过AMP和AMS通信

PMS

包是指将Apk、jar、so文件等加载到Android内存中
由一个包转变成可执行的代码。需要包管理机制来进行包的加载、解析、管理等操作

PackageManager的主要功能

  • 获取一个应用程序的所有信息
  • 获取四大组件的信息
  • 查询permission相关信息
  • 获取包的信息
  • 安装、卸载APK

PackageInstaller

  • 用于安装、卸载和更新应用程序
  • 根据Uri不同的Scheme协议不同,进行不同的隐式跳转,content协议就跳转到InstallStart,其他就跳转到PackageInstallerActivity
  • InstallStart主要的作用是将"file://Uri"转换成"content://Uri",就可以进入到PackageInstallerActivity
  • PackageInstallerActivity会对package协议和file协议的Uri进行处理,如果是file协议会解析APK文件得到包信息PackageInfo
  • PackageInstallerActivity会对未知来源进行处理,如果允许安装未知来源或者APK不是未知来源,则会初始化安装确认界面,如果限制的未知来源,则通过Dialog或跳转到设置页面来处理。
  • 点击确认安装后,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
  • 调用PackageInstaller.Session的commit方法,将APK的信息交由PMS处理

以上是关于Android 随心笔记(更新至2021.07.05)的主要内容,如果未能解决你的问题,请参考以下文章

随心笔记

python随心笔记

随心笔记---布局设计

Java 随心笔记4

Java 随心笔记5

Java 随心笔记6