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线程进行延时操作
泛型类与泛型方法
- 泛型类是在实例化类的时候指明泛型的具体类型
- 泛型方法是在调用方法的时候指明泛型的具体类型
- 泛型方法在泛型类中有以下两种情况:
- 泛型方法的泛型T 是一个全新的泛型 和类中的泛型T可以是相同类型,也可以是不同的任意类型
- 泛型方法的泛型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(10,100,10,100,10,100,10);
ValueAnimator valueAnimator = ValueAnimator.ofInt(10,100,50,30);
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系统架构(五层)
- 应用层
- 应用框架层
- 系统运行库层
- 硬件抽象层
- Linux内核层
应用层
系统内置的应用程序以及非系统级的应用程序都属于应用层。负责与用户进行直接交互。有Java、Kotlin、Flutter三种开发方式。
应用框架层
应用框架层为开发人员提供了可以开发应用所需要的API,我们平常开发应用程序都是调用这一层所提供的API开发,也包括系统的应用。
使用Java编写,被称为Java Framework
系统运行库层
又分为两个库:C/C++程序库和Android运行时库
硬件抽象层
位于操作系统内核与硬件电路之间的接口层,硬件抽象化,保护硬件厂商的知识产权,隐藏特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可以再多种平台上进行移植。简单来说:就是将控制硬件的动作存放在硬件抽象层
Linux内核层
Android的核心系统服务基于Linux内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。
Android系统启动流程
- 启动电源以及系统启动,引导程序Bootloader,Linux内核启动
- 启动init进程(第一个进程)
创建一些文件夹并挂载设备
初始化和启动属性服务
解析init.rc配置文件并启动zygote进程
- 启动zygote进程
创建AppRuntime并调用其start方法,启动Zygote进程。
创建DVM并为DVM注册JNI
通过JNI调用ZygoteLnit的main函数进入Zygote的Java框架层
通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用进程
启动SystemService进程
- 启动SystemService进程
启动Binder线程池,用于和其他进程通信
创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理
启动各种系统服务
- 启动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)的主要内容,如果未能解决你的问题,请参考以下文章