Android 随心笔记(Latest date - 05 - 12)

Posted 小柴的回忆

tags:

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

笔记


小柴的笔记

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

面向对象的三大特征

  • 多态
  • 封装
  • 继承

面向对象的五大基本原则

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

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

阿里云镜像仓库地址

buildscript 
    repositories 
        google()
        mavenCentral()
        maven url 'https://maven.aliyun.com/repository/jcenter'
        maven url 'https://maven.aliyun.com/repository/google'
        maven  url 'http://maven.aliyun.com/nexus/content/groups/public/' 
    
    dependencies 
        classpath "com.android.tools.build:gradle:4.2.2"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    


allprojects 
    repositories 
        maven  url 'http://maven.aliyun.com/nexus/content/groups/public/' 
        maven  url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' 
        maven  url 'http://maven.aliyun.com/nexus/content/repositories/google' 
        maven  url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' 
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    

Fragment的生命周期

Android 常用的设计模式(一共有23个设计模式)

  • 单例模式
  • 建造者模式(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();

        

抽象类与接口的区别

1.抽象类可以实现某些方法,而接口不行,接口只能提供定义的方法,不能有方法的实现。
2.抽象类的方法实现,只能由子类实现,且一个类只能继承一个类,而一个类可以实现多个接口
3.抽象类可以有静态方法,接口在jdk8后也可以有静态方法
4.抽象类的修饰符可以是public、protected、default,而接口默认且只能是public

String 、 StringBuffer、StringBuilder之间的区别

  • String 源码是有关键final的,所以赋值后是不可变的,我们平常用的时候,第二次赋值,其实是创建一个新的String对象
String x = "你好";
x  = "我是小柴";
  • StringBuffer,值是可以变的,不会产生新的对象,线程安全,可以多线程操作一个字符串
  • StringBuilder,值是可以变的,不会产生新的对象,线程不安全,建议单线程操作字符串,他的速度比StringBuffer更快。

handler 内存泄漏的原因

message.target = this,持有handler,而handler是内部类,持有activity

一个线程拥有多少个Handler、Message、Looper 、MessageQueue

多个Handler、多个Message、一个Looper、一个MessageQueue

匿名类

接口是不能被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)
		...
	

参考文章:java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一

可变参数

意思就是运行定义多个参数。
如下的属性动画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

OKHttp

参考文章:OKHttp3简单使用教程(一):请求与响应
HTTP请求报文格式:
请求行 + 请求头部 + 请求正文
请求行:请求方法(POST、GET)、URL、协议版本
请求头部:为请求报文添加一些附加信息,由名-值对组成
请求正文:可选内容

HTTP响应报文格式:
状态行、响应头部、响应正文
状态行:协议版本、状态码、状态描述
响应头部:与请求头部类似,为响应报文添加一些附加信息
响应正文:是请求响应的最终结果,都在响应体里面
报文可以承载多种数据类型:图片、视频、html文档、软件应用程序等
请求头与响应头的信息表http://tools.jb51.net/table/http_header

添加网络访问权限:

 <uses-permission android:name="android.permission.INTERNET" />

响应Response内容
我们希望获得返回的字符串,可以通过response.body().string()获取;
如果希望获得返回的二进制字节数组,则调用response.body().bytes();
如果你想拿到返回的inputStream,则调用response.body().byteStream()

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通信

WMS

WMS是窗口的管理者,它负责窗口的启动、添加和删除。窗口的大小和层级也是由WMS负责。窗口动画,输入系统的中转站、Surface管理

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处理

透明度列表

透明度 16进制表示
如:00FFFFFF 是百分百透明的白色,00就是ARGB中的Alpa

透明度%A的16进制数
100%00
95 %0D
90 %1A
85 %26
80 %33
75 %40
70 %4D
65 %59
60 %66
55 %73
50 %80
45 %8C
40 %99
35 %A6
30 %B3
25 %BF
20 %CC
15 %D9
10 %E6
5 %F2
0 %FF

int数据个数不够自动加0

格式为4个数,当为1时,可生成0001字符串

	int number = 1;
	DecimalFormat decimalFormat = new DecimalFormat("0000");
	String string = decimalFormat.format(number);
	TextView textView = findViewById(R.id.txt);
	textView.setText(string);

Drawable转Bitmap

	Drawable drawable
	BitmapDrawable bd = (BitmapDrawable) drawable;
	Bitmap bitmap = bd.getBitmap();
	//获取资源文件
	Drawable drawable = context.getResources().getDrawable(R.mipmap.app_logo, null);
	BitmapDrawable bd = (BitmapDrawable) (drawable);
	Bitmap bitmap = bd.getBitmap();

请勿修改AndroidManifest中,首页Activity的label属性

因为修改后,你自个的APP名字也会跟着变

关于drawable 与 drawable-v24

当我们复制一张图片进drawable时,会显示以下弹窗,改弹窗默认选择v24,但我建议存放在drawable,因为若是存放在drawable-v24的时候,当运行版本低于API24时,就无法获取该照片,导致应用闪退

去掉Button的阴影

style="?android:attr/borderlessButtonStyle"

@SuppressLint(“RestrictedApi”)

英译:抑制受限的API,无视警告

在外部获取Menu

有时候需要在外部(onCreate等地方)判断内容,在显示菜单栏中的作用。
比如,访问数据库,判断文章是不是自己的,是自己就不显示举报,是他人就显示举报,都是同一个menuItem

	Toolbar toolbar = findViewById(R.id.tool_bar);
	MenuItem menuItem = toolbar.getMenu().findItem(R.id.action_report);
	if(isSelf)
		toolbar.getMenu().removeItem(R.id.report);
	

通过颜色 int值获取ARGB的值

      int color = 0xCE54FF9F;
      int apla = (color >> 24) & 0xff;
      int red = (color >>16)  & 0xff;
      int green = (color >> 8) & 0xff;
      int blue = color & 0xFF;

以上是关于Android 随心笔记(Latest date - 05 - 12)的主要内容,如果未能解决你的问题,请参考以下文章

随心笔记

python随心笔记

随心笔记---布局设计

Java 随心笔记4

Java 随心笔记5

Java 随心笔记6