https://blog.csdn.net/qq_23575921/article/details/78947051 原文 补充
Android任务栈
singletop(栈顶复用):Android系统内置的书签应用
singletask(栈内复用):商城首页,在分页中点了主页其他的分页全部出栈
scheme跳转协议
- 在不知道对方的包名,类名的情况下要打开对方,不如浏览器要打开其他的app,或者本应用 打开 其他的应用的时候就可以采用这种方法;他是通过在activity中注册intent-filter来实现的包含 data(含scheme),cataglory,action
Fragmen相关
- addToBackStack 加入栈中,返回的时候销毁Fragment
Service和Broadcast都是运行在mainThread中所以不能做耗时操作
数据库相关
- SQLiteOpenHelper 构造方法创建数据库(方法参数一样只会调用一次,当版本号不一样的时候会调用onUpgrade方法),用这个对象的拿数据库会掉onCreate方法,这个方法里创建数据库表
- helper对象拿db对象,db对象操作数据库,这些操作的方法封装到Dao里面提供给外面调用
获取 Message 的方法
- 在 Hanlder 机制中都需要用到 Message 对象,该对象的创建或者获取有多种方式。
- Message msg = new Message(); 直接创建一个新的 Message 对象。
- Message msg = handler.obtainMessage(); 通过 handler 对象获取一个 Message 对象,该对象从消息缓存池中获取的,可以提高 Message 的使用率,减少垃圾回收次数。
- handler.post(Runnable r); post()方法中传递一个 Runnable 对象,那么该对象会被主线程执行。该方法表面上看跟 Message 没任何关系,但是其内部帮我们封装了 Message。
- 同样View.post 也是同样的机制
常用的线程调度操作
- 通过View对象执行延时操作
View view = ...;
view.postDelayed(new Runnable() {
@Override
public void run() {
}
}, 200);
- 通过Handler发送延时请求(可以在子线程发出)
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
}
}, 3000);
本质是sendmessage,让后把runnable一起传出去,代替了handlemessage
- 在子线程执行Activity中的runOnUiThread方法
new Thread(){
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
};
}.start();
### 有关动画
- 属性动画animator:是为动画设置执行的客体,然后指向动画
- 补间动画animation:是为客体指定要执行的动画
广播:要注册清单文件
- 注册广播:写好广播接受者类,完成onrecevie方法
- 静态注册:在清单文件里注册广播写好意图过滤(杀死进程,都可以收到广播,但是不灵活)
- 动态注册:在代码中注测action吗(受activity生命周期影响)
- 实现机制
- 通过binder向AMS注册广播接收者 :登记接收者
- 通过binder向AMS发广播:登记广播
- AMS找到对应的接收者,把广播放在接收者的消息队列中
- 接收者回调onreciver
myReceiver = new OutCallReceiver();
IntentFilter intentFilter=new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
intentFilter.setPriority(Integer.MAX_VALUE);
registerReceiver(myReceiver,intentFilter);
Intent intent = new Intent();
intent.setAction("com.itheima.cnr.XWLB");
intent.putExtra("content", "这里是中央人民广播电台! 欢迎收听!");
sendBroadcast(intent);
- 有序:各级接受者要配置priority,高的可以中断广播,内线一定可以接收到最后一个结果
sendOrderedBroadcast(
intent,
null,
new NeixianReceiver(),
null,
1,
"中央下发粮食了, 每人1000斤, 大家吃好喝好!",
null
);
- localbroadcastmanager(本地广播)
- 防止反编译到action,利用你的app分享他自己的连接(植入广告)
- 比系统广播更高效
- 别的app无法向你发广播。只在本app传播
- 不同于系统广播发送通过binder,本地广播发送是通过handler
android中任务栈情况,但是进程依然保留(为了下次打开快)
- 一个应用可以run在多个进程中
- 前台进程(可以操作),可视进程(被透明的前台遮挡,不能操作),服务进程(没有界面的程序),后台进程(home键回到主界面),空进程(任务栈清空,按返回键造成)—按优先级回收
服务:要注册清单文件
- 启动和显示意图的activity一样,反复开启(startservice)不会走oncreate,只会执行onstartcommand
- 关闭要到设置里,或者手动调stopservice走一次ondestroy
绑定服务的方法
- 创建连接对象,实现连上和解开两个方法,在服务的绑定和解绑服务中被回调
- 绑定服务传入的是conn和service
- 服务被绑定要传回一个ibinder对象,用这个ibinder来通信
- 要解绑,否则连接器会leak,服务会自动销毁
- 服务是被start打开的,主程序意外退出,服务不会退出;如果服务是bind方式打开,主程序意外退出(没有手动unbind),服务会自动解绑并且destroy
- 总结是前台进程通过绑定conn和服务的方式启动服务,服务返回ibinder对象给前台进程,ibinder对象可以带上服务里的方法给前台进程调用
- 当 service 同时被 startService 和 bindService 启动时,只有 stopService 和
unbindService 都被调用后,service 才会被销毁。
单例吐司
if(toast == null){
toast = Toast.makeText(context, "", Toast.LENGTH_SHORT);
}
toast.setText(string);
toast.show();
隐式意图应用间用,用了意图过滤器or export=true那么就可以被其他应用打开;显示意图默认是应用内部用
aidl(服务代码在另一个应用中 接口定义语言)
- 是一种采用共享存储区的IPC通信方法,通过asinterface的方法用key值在共享文件binder中找到服务接口,返回给调用对象使用;调用者用aidl生成的类里的方法处理返回的binder对象可以生成远程服务指定的接口类,并调用其中的方法,达到调用服务里方法的目的
既然service不能做耗时操作,也要new thread 那么为什么不直接在 activity中new thread;
- 因为activity会销毁finish ,很难对线程做到很好的管理,但是service就不同,可以长时间在后台运行,完成对thread的管理。比如音乐播放器、数据统计。
- activity与service的通信用的是binder机制,这本身就是IPC通信的原理,应为activity和service完全可以运行在不同的进程当中。
服务可以不用直接和activity交互,通过startservice方式启动的服务,可以发送广播给接收者,让广播处理相应的业务。让activity和service之间解绑。
webview
- 内存泄漏:自己会开辟线程(类似匿名内部类持有外部类的引用)不懂
- 动态通过viewgroup添加,销毁前remove
- 独立进程
- 渲染:关闭硬件加速
- 耗电:
binder机制
- Linux是进程间隔离的,进程之间没有办法传数据
- 所以通过第三者servicemanager来管理,传回一个代理对象给client
- client把代理对象调的结果告诉binder,binder调service里的真方法
aidl机制
- stub实现了IService接口,
- 在asinterface里面按照key查找本地的接口,如果有就表示是本地的调用直接返回,如果没有则返回proxy代理对象
- 代理对象实现的方法是个空方法,调用了transact,最终回到onTranact,调用的还是本地的方法,中间通过了Ibinder
内存泄漏https://blog.csdn.net/bigbangwqf/article/details/51329223
- 非静态内部类持有外部类的引用(静态的不会持有,跟对象无关):handle
- 可以关闭的时候销毁掉 handle.removecallback()
- 可以弱引用
- 可以静态化(这样调不了外部类的方法)
- 匿名内部类持有外部类的引用:webview
AsyncTask使用方法
- 三个参数(传入,进度,结果)
- 五个方法:
- onPreExecute:在UI线程调用,任务前准备工作
- doinbackground<第1个参数>:耗时
- 结果传入:onPostExecute<第3个参数>
- 更新进度:publishProgress(内部),onProgressUpdate<第2个参数>(外部跟新)
- 原理:内部封装线程池,用handle实现子线程和ui线程的传递
- 泄漏:cancel
HandlerThread相关
- 处理串行的子线程调用
- 继承类消息群是在prepare里完成插入,同时创建handle,定义处理消息的处理方式handlemessage
![BAT大咖助力 全面升级Android面试笔记 (自己补充)_第1张图片](http://img.e-com-net.com/image/info8/a381ab41ac5841cdb9e1de5fc93f1693.jpg)
IntentService相关
- https://blog.csdn.net/iromkoear/article/details/63252665
- 消息群是在onstart里完成插入(IntentService已经插入), 继承类定义处理消息的处理方式onhandleintent
Android studio
- classpath ‘com.android.tools.build:gradle:3.0.1’ 这个跟Android studio的版本一样
- compileSdkVersion :sdk/plateform
- buildToolsVersion :sdk/build-toos
- 目录:
- .gradle:构建文件
- gradle:由于gradle更新的速度超过Androidstudio所以弄了个包装类wrapper来跟上进度。
- .idea:Androidstudio自己要用的工具
listView 优化
- convertview重用: 不用new
- viewHolder : 不用找
- 图片缓存 :不用每次都加载
- 滑动监听:尽量不要做耗时操作,一定要做的话,加滑动监听,停下来的时候在请求网络等等
类加载器的双亲委托模型
- 先交给最顶层的加载器加载
- 步骤:
- 加载
- 验证
- 准备:赋值,局部变量一定要赋值才能使用,否则编译不通过,其他的按照jvm的规则进行赋值or默认值;同时被static和final修饰的要在声明是就赋值,final修饰的要在初始化前赋值;
- 解析:解析类、方法、变量,方法先找类
- 初始化
- 使用
- 卸载
内存管理
- 静态存储器(方法区):静态数据,常量;存在于整个生命区
- 栈区:基本类型变量,对象引用
- 堆区(动态存储器):
- 回收机制
git 命令
- git init
- git status
- git diff
- git add
- git commit
- git clone
- git branch
- git checkout
- 下面的模型区别于传统的直接跟远程仓库打交道,忽略了代码管理员的角色,增加了fork和pull
![BAT大咖助力 全面升级Android面试笔记 (自己补充)_第2张图片](http://img.e-com-net.com/image/info8/ef5e3683d7854648bee183be7f0d1d6e.jpg)
proguard
框架
volley
-支持图片加载
- 使用:
- 源码:
- 创建请求队列:封装了httpclientstack,创建了queue开启并返回
- queue开启创建了两个线程死循环,一个是缓存线程,一个是网络请求线程
- 在请求加入请求队列后
- 判断是否要缓存,要就加入缓存线程
- 加入网络请求线程
- 其中缓存线程的run方法会先按照key从缓存队列中拿,返回为空,就把他加入网络请求队列。发出返回结果,触发回调函数
- 而网络请求队列是直接加入请求,发出返回结果,触发回调函数
butterknife
- 是用注解在编译期完成的,并非运行时反射的
- 变量要是public否则只能反射才能获得
开发架构
MVC
- M:业务逻辑,耗时,数据库
- V:显示,xml
- C:activity 处理交互,从v拿到用户输入的数据,交给m查数据库or请求服务器,返回的结果交给v显示;解耦v 和 m
MVP
-
由于Android的v(xml)所做的的详情,相比于web来说非常有限。很多工作交给了c层的activity实现导致C太耦合了,所以引入MVP
-
在MVP中activity变成了v,他原本的处理交互的工作交给了presenter来处理
-
M:网络请求,数据库查询,数据bean
-
V:activity
-
P:业务层,彻底分开view和model
-
![BAT大咖助力 全面升级Android面试笔记 (自己补充)_第3张图片](http://img.e-com-net.com/image/info8/426bbf19902742669680031a8c5f3ae3.jpg)
-
上图可以清晰的看到presenter要调view,只能通过定义好的接口,限制好能做的事
-
**特点:**与业务有关的M(网络请求,数据库查询)或V(成功返回,失败返回,显示关闭进度条) 都是要在接口中定义好交给对应的M 或者V (activity)实现,让代码看的结构清晰。就是P要调用v还是M都是接口定义好的只要看接口就知道要做什么事。
-
接口回调:网络请求为例,我不知道请求几时能结束,所以把结束要做的事的函数跟着网络请求一起传给请求函数,请求结果出来了由他回调。在Android里这个回调方法执行一般要更新ui,所以要交给handler处理(runonuithread就是这么封装的)。
PathClassLoader,DexClassLoader
- DexClassLoader:加载dex字节码里的类(动态)
- PathClassLoader:加载文件目录里的类
有关进程的优先级
- 空进程的存在是为了缓存,下次打开apk快一些,不包含任何组件
- 进程回收:low memory kill 打分
- 保活:service拉活,native拉活
Android中哪些操作在主线程
- Activity的所有生命周期方法
- Service执行
- 广播的onReceive
- 没有使用子线程的Looper的Handler的HandleMessage,post是执行在主线程的
- AsyncTast的回调中除了doInbackgound,其他都是在主线程的
如何解决ANR
- 使用AsyncTast处理IO操作
- 使用Thread或者HandlerThread提高优先级
- 使用Handler来处理工作线程的耗时任务
- Activity的onCreate和onResume回调中尽量避免耗时的代码
oom
- 当前占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存限制就会抛出Out Of Memory异常
内存泄漏:
- 单例:单例是静态的,传入的context用application。
- 匿名内部类(就跟非静态的内部类泄漏是一样的原因,默认持有外部类的引用,不是说静态的就不可以持有,如果构造方法传进去了就会持有,但是可以改成弱引用):非静态的都会持有外部类的引用。内部不消失,外部不消失
- 匿名内部类指的是类定义的时候没有给名字,而不是这个类生成的对象没有给名字。通常类在定义的时候就new了比如thread。
- 所以有:匿名内部类访问方法成员变量需要加final的原因及证明
- 解法:弱引用
- handle:定义在activity的匿名handle内部类,生命周期和activity不一样,他是被消息队列持有,只要队列的消息没完就不会消失。
- 解法:静态,对持有外部类的引用改为弱应用弱引用
- static成员变量:避免使用
- 资源没有关闭
- asynctask,可以在onDestroy 取消任务