| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Learn-1 -> 正文阅读 |
|
[移动开发]Learn-1 |
点击图标启动: 首先launcher进程通过binder IPC方式向System_server(AMS)发起StartActivity请求 System-server(AMS)通过socket方式向zygote进程发起创建新的APP进程请求 zygotefork出新的APP进程,这个进程通过IPC告诉system-server发起attachApplication请求 system-server(AMS)收到之后,其中的ApplicationThreadProxy又通过ipc的方式给APP进程发送scheduleLaunchActivity请求 APP进程中的binder线程ApplicationThread接收这个请求之后,通过handle向主线程ActivityThread发起LAUNCH_ACTIVITY,主线程通过反射机制创建目标activity,并回调其onCreate方式。 四种场景: standard,默认模式,每次都会创建新的Activity SingleTop,如果在栈顶,则不创建,直接调用activity的onNewIntent方法,不在栈顶,则创建新的实例 SingleTask,如果在归属的栈中存在,则将其上面的所有activity出栈,并调用onNewIntent方法, SingleInstance,每次都创建一个新的栈,然后创建新的activity ANR场景: Server TimeOut:前台服务20s,后台服务200s,超时未执行完成 BroadCastQueue TimeOut: 前台广播10s,后台60s,超时未处理完广播 ContentProvider TimeOut: publish 10s没完成 Service? 两种方式 startService onCreate onStartCommand? onDestroy,如果服务已经开启,多次执行startService,只会调用onStart()-》onStartCommand,销毁直接调用StopService,与调用者无关 bindService onCreate onbind onUnbind onDestroy,如果服务已经开始,多次执行bindService,不会多次调用onBind()销毁需要调用unBindService 或者 调用者退出了,服务自动调用unBind()-》onDestroy终止。 启动流程: AMP进程通过binder ipc方式向AMS发起StartService请求, AMS使用socket向zygote发起新进程的请求 zygote通过socket方式fork出一个新进程Remote Service进程 Remote Service进行通过IPC方式向AMS发起attachApplication请求 AMS通过ApplicationThreadProxy发送scheduleCreateService请求给Remote Service进程中的ApplicationThread这个binder线程,它收到请求之后通过handle向主线程ActivityThread发送CREATE—Service消息 主线程ActivityThread通过反射机制,创建目标Service,并回调其onCreate方法 如果是本地服务或者服务所属的进程已经创建,就跳过zygote这一步。 handle 原理 子线程创建的时候会调用Looper.myLooper()来判断是否looper为null,是的话则报错,所以子线程中需要调用Looper.prepare()之和再创建handle对象。 其中线程切换原理:在主线程中创建handle的时候,会把主线程MainThread和创建的looper绑定,,而在子线程中调用handle发送消息的时候,主线程的looper通过循环拿到消息了,这样通过looper关联的主线程,就可以操作消息了,这样就是handle的线程切换 handle,发送Message消息到MessageQueue,loop会将msg送给绑定的handle中 Message,封装的消息对象,使用Message.obtain创建对象。因为可以检查是否有可以复用的Message,用过复用避免过多的创建、销毁Message对象达到优化内存和性能的目地 MessageQueue,单链表的数据结构 Loop,循环查询MessageQueue里面的消息,一个线程里面只能有一个,创建使用
? ? ? ? ? ? ?2.
model:网络请求,数据库处理 controller: 缺点:activity承担了view和controller的角色,解耦程度不够。
present:更新UI 缺点:双向依赖,UI改变,P也要改变,由于P持有activity,导致处理耗时的操作时候,内存泄漏的风险,使用弱引用解决这个问题。 mvvm: view:xml,activity model:网络请求 ViewModel:存储UI状态,处理逻辑请求,将数据设置成观察者容器 主要是view可以通过观察者模式,如果viewmodel层有数据更新了,view就自动更新,不需要在viewmodel层写回调方法,解决了mvp中V跟P相互依赖的问题 MVI: view: intent: model: viewState Surfaceview 拥有独立的绘图表面,可以在独立的线程中进行UI操作,不会影响主线程,在Surfaceflinger中拥有独立的layer 在Surfaceview中的onAttachToWindow的函数里面会调用mParent.requestTransparentRegion();来告诉activity去设置一块透明的区域,这样才可以看到SurfaceView的图层,因为SurfaceView默认的图层Z坐标小于activity的z坐标。 相当于默认的activity图层在Surfaceview图层。 TextureView 在主线程Activity中绘制的,需要在CPU,GPU这三者之间进行同步,如果同步出错,会出现掉帧,卡顿和抖动的情况, TextureView可以通过屏幕截图或者getBitmap得到视频画面,而SurfaceView不可以。 GLSurfaceView 提供OpenGL将内容渲染到Surface上,使用单独的GLThread在设置render之后创建,继承自SurfaceView 音频播放SDK MediaPlayer:适合后台长时间播放本地文件或者在线音频 SoundPool:适合播放端的音频片段,游戏声音,铃声,可以同时播多个音频 AudioTrack:适合低延迟的播放,适合流媒体播放,需要结合解码器使用 音频播放NDK层 OpenSL ES:强大的音效处理,低延迟播放。可以实现实时耳返的功能。 FFmpeg 拼接 裁剪 加速 转场 OpenGL 图像缩放,特效,裁剪,叠加,模糊,滤镜 缩放:在顶点着色器里面添加rotate旋转,scale缩放矩阵,去乘以顶点坐标,就可以 叠加,水印:通过OpenGL的blend混合模式,将两个Texture同时绘制上去,形成叠加状态,也可以用openCV进行像素叠加 滤镜:通过切换不同的shader文件,主要是在片段着色器里面,将顶点着色器传过来的纹理坐标,对应图片纹理上的像素点,通过修改像素点的颜色来设置滤镜 性能优化 包大小: Proguard 混淆,使用代码混淆,可以去掉无效的代码,并简化代码 lint检查,删除没有用到的资源文件,资源图片进行压缩,选择合适的图片格式,比如webp的有损压缩能比jpg小25-34% lib优化,去掉不常用的CPU架构库文件,比如arm64-v8a向下兼容v7a的。 启动优化: Application创建过程优化:设置异步和同步加载两个函数,耗时操作放入异步加载中 MainActivity创建过程优化:同样设置异步加载,如果必须在主线程中的加载,可以设置延迟加载,等首屏绘制完成再去加载。 布局优化,减少布局层级,减少首次加载的view的数量 SDK等资源可以懒加载,需要的时候再去加载。Bitmap复用 view层级复杂,使用ConstarintLayout,如果view层级简单使用LinerLayout,这个比ConstraintLayout和RelativeLayout渲染耗时都要少 使用ViewStub控件,需要的时候才加载 内存优化: 使用线程池创建线程,onDraw避免创建对象 StringBuilder 代替String 拼接字符 rebase 和merge的区别: merge命令不会保留merge的分支,不会产生commit,合并两个分支为一个新的提交。 rebase 会取消当前分支中的每个提交,然后重新设置基线,最后把自己的之前提交放到这个基线的后面,比如你同事在master更新了提交,你想基于这个提交来更新自己的commit,就可以通过rebase的方式,将自己的提交放在同事的提交的后面。 cherrypick 用于拷贝某一次的提交。 malloc 和new的区别: new 是操作符在调用的时候,先分配内存,再调用构造函数,delete的时候调用析构函数。new? 可以被重载,只可以分配对象所占内存的整数倍大小,内存分配在自由存储区,可以是堆,也可以是其他地方 malloc 是函数,直接分配内存,调用free释放,可以分配任意大小的字节,内存分配都在堆里面 System.Load加载流程 Java层调用System.loadlibrary("ffmpeg"),会调用Runtime中的loadlibrary,这个里面首先调用findlibrary去查找so文件是否存在,如果存在则调用nativeLoad. findlibrary过程,首先在应用内查找so文件,data/app/packagename/lib/arm,如果没有找到,则去系统里面寻找,vendor/lib或者system/lib 如果zygote收到AMS需要fork出64位的进程的话,则去vendor/lib64或者system/lib64里面寻找 然后通过nativeLoad 加载so文件,先判断是否加载过so,如果加载过,则判断是否是同一个ClassLoader,如果一致,返回上次的加载结果,不一致则报错。 然后通过dlopen 打开so,使用dlsym 获取jni_on_load函数指针地址,最后通过jni_on_load返回加载是否成功。 最后可以通过dlopen返回的句柄来调用so里面的函数。 Boost 里面 c++ 智能指针: scoped_ptr, 不支持拷贝和赋值的操作,防拷贝的实现原理:将拷贝构造函数和赋值运算符进行重载,只声明私有 不实现,在C++11里面自带unique_ptr 跟这个效果一样,不共享对象,如果转移到另外一个unique_ptr则原始的不再拥有对象,使用reset绑定对象,move转移对象拥有权,release释放拥有权 shared_ptr,共享指针,里面有引用计数,有循环引用问题,C++11里面自带shared_ptr效果一样 weak_ptr,弱指针,配合shared_ptr使用,解决循环引用问题,因为weak_prt不拥有这个空间,所以不会增加shared_ptr的引用计数 instrusive_ptr,类似share _ptr,需要自己实现指针计数 scope_array,针对数组 share_array,针对数组 C++里面没有这两个针对数组的智能指针,需要采用定制删除器的方式: template<class T> struct Delete { void operator()(T* ptr) { delete ptr; } }; jni层内存泄漏检测工具: MemoryLeakDetector,https://github.com/bytedance/memory-leak-detector/blob/master/README_cn.md 进程间通信: binder,只需要一次拷贝,Binder IPC 机制中涉及到的内存映射通过 mmap() 来实现,mmap() 是操作系统中一种内存映射的方法。内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。 socket,zygote和AMS通信就是通过socket。 contentprovider,基于binder AIDL,基于binder TCP 三次握手解释:因为TCP是全双工的,client需要给server发数据,而server也要给client发数据。所以第一次是client向server监听的端口发送连接请求,服务器同意连接的同时,还需要给client发送连接请求,所以这是第二次,最后client给服务器发送确认连接的消息之后,双方都进入已连接状态。 okhttp rxjava eventbus:通过创建单例模式,在注册的时候通过反射查找方法,使用观察者模式,内部使用hashmap保存订阅的列表 socket rtmp: 首先进行client和server握手,client发送C0,C1,C2三个有序的chunk,server发送S0,S1,S2三个chunk 异常处理机制 音频混音原理: 线性相加:通过把同一声道的数值相加,如果16bit整数,两个字节能够表示的有符号整型数的范围是-32768~32767。如果相加溢出了,直接使用最大正数32767或者最大负数-32768 平均调整权重:通过把同一声道的数值相加之和,除以通道数 归一化:通过把同一声道的数值相加之和去乘以归一化因子 activity缓存: 如果系统未经用户允许,停止activity的时候,会调用onSaveInstanceState 让用户去保存一些临时数据,重新onCreate的时候,可以通过onSaveInstanceState的bundle获取保存的数据,也可以通过onRestoreInstanceState去获取 C++指针和引用的区别: 引用不能为null,指针可以 指针的内容是指向这块内存的地址,而引用是这块内存的别用名 指针使用++ 则会指向这块内存的邻居下一个内存的地址,不再指向这块内存了,而引用这是将这块内存中的值自增,如果这块内存保存的值为1,则变成2 动态代理:运行的时候通过反射创建代理类,可以根据需要创建不同的代理类? 静态代理:直接在编译之前就创建代理类。 Android 类加载机制: 核心是父类加载器能否胜任加载工作,如果不能则继续往上递归,如果最终所有的父类都不能完成加载,则自己才加载。代码流程: findLoadedClass(className)-》失败则判断parent是否为null 否则调用parent.loadClass(className); 是则调用findBootstrapClassOrNull(className) 如果上面都失败,则自己来找调用findClass(className),这个方法调用在BaseDexClassLoader里面的findClass,主要是DexPathList.findclass,而DexPathList则是在dexElement数组里面寻找,dexElement数组是在maxDexElements这个函数赋值的 而这个函数第一个参数是APK编译打包的Class.dex的路径。所以热修复就是把打包好的补丁包patch.dex通过maxDexElements合并到dexElement数组里面去。 热修复:流程就是通过反射拿到类加载里面的elements数组,然后通过maxDexElements方法解析打包的patch.dex文件,拿到里面的elements数组,然后跟原来的dexElements数组进行合并,放到原来的前面。Android中PathClassLoader用于加载APP的类,bootClassLoader加载系统的类,而热修复一般是DexClassLoader可以指定加载的dex文件目录,而pathclassloader只能加载系统默认位置,Android8。0开始 DexClassLoader也只能加载系统默认位置。 Android onCreate里面获取view的宽高: 通过调用view.post(new Runnable) Surfaceview 显示Camera流程 C++值传递和引用传递 示例:
int FunA(const int m) // 值传递, main(){ int a = 1; FunA(a); } 这里实际上是代表:int m = 1;对m初始化值为1,所以函数里面改变m的值 并没有改变a的值
然后是引用传递,编译系统会在调用函数的时候,把实参的内存地址(指针)传给形参,那么形参和实参指向同一块内存,改变形参的值,就是改变实参的值,int FunB(const string & strTest)
int FunA(const int &m) // 引用传递 main(){ int a = 1; FunA(a); } 这里实际上是初始化int &m = a; m代表的是a,改变m指向的内存数据就是改变a指向的内存数据
|
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年4日历 | -2025/4/19 1:32:19- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |