Java和c没有什么说的
常见的设计模式单例模式、工厂模式、观察者模式、代理模式、适配器模式、建造者设计模式 、中介者模式、模板设计模式
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。
其实我们日常开发中的Activity,Fragment和XML界面就相当于是一个 MVC 的架构模式,Activity中不仅要处理各种 UI 操作还要请求数据以及解析。这样的后果就是Activity可能会有几千行的代码,不便于维护,基于此现象及解耦的原则,才使用MVP的架构模式进行分离代码,其次MVP便于后期的代码重用,比如相同的业务逻辑,不同的ui界面等,开发MVP框架最重要的注意事项是内存泄漏。
参考文章:https://blog.csdn.net/johnny901114/article/details/54783106
搭建一套MVP架构框架:
*中介者设计模式
*Base基类的设计
*静态代理生命周期
*P层的安全、内存友好设计
*APT 在 MVP 框架中应用,提高车速
MVP架构由MVC发展而来。
在MVP中,M代表Model,V代表View,P代表Presenter。
Model 负责获取数据,数据的来源可以是网络或本地数据库等;
View 负责界面数据的展示,与用户进行交互;
Presenter 是Model与View之间的通信的桥梁,将Model与View分离开来。
具体实现的步骤
所以MVP的架构有如下好处:
1)降低了View和Model的耦合,通过Presenter层来通信;
2)把视图层抽象到View接口,逻辑层抽象到Presenter接口,提高了代码的可读性、可维护性;
3)Activity和Fragment功能变得更加单一,只需要处理View相关的逻辑;
4)Presenter抽象成接口,就可以有多种实现,方便单元测试。
TCP/IP 四层 应用层 传输层 网络层 物理+数据链路层
HTTP 三次握手 客户端向服务器发出连接请求报文
TCP服务器收到请求报文后,如果同意连接,则发出确认报文
TCP客户进程收到确认后,还要向服务器给出确认。
四次挥手
客户端进程发出连接释放报文,并且停止发送数据
服务端收到这个FIN,他发回一个ACK(确认)
服务端发送一个FIN(结束)到客户端,服务端关闭客户端的连接
客户端发送ACK(确认)报文确认,并将确认的序号+1,这样关闭完成。
HandlerMessage-》dispatchMessage-》Looper(loop)-》ActivityThread(main)-》主线程
1.Looper.prepareMainLooper();创建Looper和MessageQueue。
2.Looper.loop();获取当前线程的Looper和MessageQueue, 开启死循环获取MessageQueue的Message, 获取不到return, 获取到后调用Handler 的dispatchMessage,然后给客户端回调handleMessage()。
监听器的使用:1.事件方顶定义接口,定义回掉的函数,并且提供set方法
2.哪里需要哪里回掉方法
3.监听放设置监听器,重写回掉的方法
弊端: 必须定义接口
发布方与监听方耦合在一起了
使用广播弊端:比较复杂,并且在UI线程,需要手动切换
Eventbus的使用
Subscriber事件的订阅方 注册,事件处理@Subscribe,不用的时候解除注册
Publisher事件的发布方 发布事件
提供线程模式POSTING()在那个线程发布 就在这个线程
MAIN()运行在主线程
MAIN_ORDERED()运行在主线程()事件发布方不需要阻塞
BACKGRIUND ()运行在不同线程
ASYNC()运行在新开的线程
粘性事件:
先发布---》再订阅
发布直接发布postSticky()
订阅-》注册-》使用方法(sticky=true)-》解注册
事件分发机制
onTouchEvent:触摸事件的处理
dispatchTouchEvent:传递触摸事件
onInterceptTouchEvent:拦截事件传递
requestDisallowedInterceptTouchEvent(boolean disallowIntercept):请求自己的父布局不要拦截事件
1、安卓中事件的消费会 优先让子View去处理。
2、如果ViewGroup很想处理这个事件怎么办? onInterceptTouchEvent
3、requestDisallowedInterceptTouchEvent 请求ViewGroup不要去处理这个事件。
OkHttp的简单使用
1. 创建⼀个 OkHttp 的实例
OkHttpClient client = new OkHttpClient.Builder().build();
2. 创建 Request
Request request = new Request.Builder()
.url("http://xxx.com")
.build();
3. 创建 Call 并发起⽹络请求
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException
{
Log.d("okhttp response", response.body().string());
}
})
OkHttp的源码解析
OkHttpClient 相当于配置中⼼,所有的请求都会共享这些配置(例如出错是否重试、共享的
连接池)。
Dispatcher dispatcher :调度器,⽤于调度后台发起的⽹络请求,有后台总请求数和
单主机总请求数的控制。
List
List
传输(⽤于 HTTP)还是某个版本的 TLS(⽤于 HTTPS)。
List
rengwuxian.com
2
⾥。
List
置到这⾥,例如如果你想查看返回的 301 报⽂或者未解压的 Response Body,需要在这⾥
看。
CookieJar cookieJar :管理 Cookie 的控制器。OkHttp 提供了 Cookie 存取的判断⽀
持(即什么时候需要存 Cookie,什么时候需要读取 Cookie,但没有给出具体的存取实现。
如果需要存取 Cookie,你得⾃⼰写实现,例如⽤ Map 存在内存⾥,或者⽤别的⽅式存在
本地存储或者数据库。
Cache cache :Cache 存储的配置。默认是没有,如果需要⽤,得⾃⼰配置出 Cache 存
储的⽂件位置以及存储空间上限。
HostnameVerifier hostnameVerifier :⽤于验证 HTTPS 握⼿过程中下载到的证书所
属者是否和⾃⼰要访问的主机名⼀致。
CertificatePinner certificatePinner :⽤于设置 HTTPS 握⼿过程中针对某个
Host 的 Certifificate Public Key Pinner,即把⽹站证书链中的每⼀个证书公钥直接拿来提前
配置进 OkHttpClient ⾥去,以跳过本地根证书,直接从代码⾥进⾏认证。这种⽤法⽐较少
⻅,⼀般⽤于防⽌⽹站证书被⼈仿制。
Authenticator authenticator :⽤于⾃动重新认证。配置之后,在请求收到 401 状
态码的响应是,会直接调⽤ authenticator ,⼿动加⼊ Authorization header 之后
⾃动重新发起请求。
boolean followRedirects :遇到重定向的要求是,是否⾃动 follow。
boolean followSslRedirects 在重定向时,如果原先请求的是 http ⽽重定向的⽬标是
https,或者原先请求的是 https ⽽重定向的⽬标是 http,是否依然⾃动 follow。(记得,
不是「是否⾃动 follow HTTPS URL 重定向的意思,⽽是是否⾃动 follow 在 HTTP 和
HTTPS 之间切换的重定向)
boolean retryOnConnectionFailure :在请求失败的时候是否⾃动重试。注意,⼤多
数的请求失败并不属于 OkHttp 所定义的「需要重试」,这种重试只适⽤于「同⼀个域名的
多个 IP 切换重试」「Socket 失效重试」等情况。
int connectTimeout :建⽴连接(TCP 或 TLS)的超时时间。
int readTimeout :发起请求到读到响应数据的超时时间。
int writeTimeout :发起请求并被⽬标服务器接受的超时时间。(为什么?因为有时候
对⽅服务器可能由于某种原因⽽不读取你的
client.newCall实际上是去执行RealCall.newRealCall()RealCall是Call接口的实现,最终返回RealCall对象。
当调用enqueue方法其实是执行的RealCall的enqueue方法其实是调用的Dispatcher的ExecutorService线程管理工具去执行,在此会判断线程的数量64,线程管理创建新的线程执行run方法里执行excute的Okhttp里面最核心的getResponseWithInterceptorChain
getResponseWithInterceptorChain() ⽅法做的事:把所有配置好的 Interceptor 放在
⼀个 List ⾥,然后作为参数,创建⼀个 RealInterceptorChain 对象,并调⽤
chain.proceed(request) 来发起请求和获取响应。
在 RealInterceptorChain 中,多个 Interceptor 会依次调⽤⾃⼰的 intercept() ⽅
法。这个⽅法会做三件事:
1. 对请求进⾏预处理
2. 预处理之后,重新调⽤ RealIntercepterChain.proceed() 把请求交给下⼀个3. 在下⼀个 Interceptor 处理完成并返回之后,拿到 Response 进⾏后续处理
从上到下,每级 Interceptor 做的事:
⾸先是开发者使⽤ addInterceptor(Interceptor) 所设置的,它们会按照开发者的要
求,在所有其他 Interceptor 处理之前,进⾏最早的预处理⼯作,以及在收到
Response 之后,做最后的善后⼯作。如果你有统⼀的 header 要添加,可以在这⾥设置;
然后是 RetryAndFollowUpInterceptor :它负责在请求失败时的重试,以及重定向的
⾃动后续请求。它的存在,可以让重试和重定向对于开发者是⽆感知的;
BridgeInterceptor :它负责⼀些不影响开发者开发,但影响 HTTP 交互的⼀些额外预
处理。例如,Content-Length 的计算和添加、gzip 的⽀持(Accept-Encoding: gzip)、
gzip 压缩数据的解包,都是发⽣在这⾥;
CacheInterceptor :它负责 Cache 的处理。把它放在后⾯的⽹络交互相关
Interceptor 的前⾯的好处是,如果本地有了可⽤的 Cache,⼀个请求可以在没有发⽣
实质⽹络交互的情况下就返回缓存结果,⽽完全不需要开发者做出任何的额外⼯作,让
Cache 更加⽆感知;
ConnectInterceptor :它负责建⽴连接。在这⾥,OkHttp 会创建出⽹络请求所需要的
TCP 连接(如果是 HTTP),或者是建⽴在 TCP 连接之上的 TLS 连接(如果是 HTTPS),
并且会创建出对应的 HttpCodec 对象(⽤于编码解码 HTTP 请求);
然后是开发者使⽤ addNetworkInterceptor(Interceptor) 所设置的,它们的⾏为逻
辑和使⽤ addInterceptor(Interceptor) 创建的⼀样,但由于位置不同,所以这⾥创
建的 Interceptor 会看到每个请求和响应的数据(包括重定向以及重试的⼀些中间请求
和响应),并且看到的是完整原始数据,⽽不是没有加 Content-Length 的请求数据,或者
Body 还没有被 gzip 解压的响应数据。多数情况,这个⽅法不需要被使⽤;
CallServerInterceptor :它负责实质的请求与响应的 I/O 操作,即往 Socket ⾥写⼊请
求数据,和从 Socket
Glide相关的面试知识点:
https://muyangmin.github.io/glide-docs-cn/
2.Glide的with方法不光接受Context,还接受Activity 和 Fragment,Context会自动的从他们获取
3.Glide支持加载各种各样的图片资源,包括网络图片、本地图片、应用资源、二进制流、Uri对象等等
4.placeholder()方法添加占位图
5.diskCacheStrategy()方法使用缓存机制
6.error(R.drawable.error)异常占位图
7.默认支持加载gif图片,asBitmap()方法只允许加载静态图片,asGif()支持加载gif图片
8.Glide对图片进行处理用多少加载多少,节省内存。
9.支持图片大小的加载override(100, 100)
1.RequestOptions多次加载解决的办法:可以使用静态的方法,封装使用
2.MyAppGide继承AppGilideModule加上注解@GildeModel配置,设置配置只加载一次,可以设置一些配置的内容如缓存、动画、监听、日志,registerComponents里面的参数registr.append可以加载资源类型和资源加载器
MyGildeExtension加上注解GildeExtension,声明方法构造传递RequestOpentions对象,对opentions进行统一配置,并且此方法要有注解@GildeOptentios,此方法是全局同意配置,然后再GildeAapp里面去调用injectOpentions()
Glide源码解析
With()
Glide会根据我们传入with()方法的参数来确定图片加载的生命周期,并没有什么特别复杂的逻辑。
Load()
给load()方法传入不同类型的参数,这里也会得到不同的ModelLoader对象。由于我们刚才传入的参数是String.class,因此最终得到的是StreamStringLoader对象,它是实现了ModelLoader接口的,并且DrawableRequestBuilder实现Glide绝大多数的API
Into()
DrawableRequestBuildersuper是父类是GenericRequestBuilder里面的into()
Request是用来发出加载图片请求的,它是Glide中非常关键的一个组件,在构造的过程中把placeholderId、errorPlaceholder、diskCacheStrategy等等都是在这里组装到Request对象当中的。
加载图片最终显示出来,默认使用的HttpUrlConntion同时也支持Volley和Okhttp进行拓展
Gilde的缓存机制
lide又将它分成了两个模块,一个是内存缓存,一个是硬盘缓存。
情况下Glide会优先从缓存当中读取,只有缓存中不存在要读取的图片时,才会去读取原始图片。
内存缓存:skipMemoryCache()方法并传入true,就表示禁用掉Glide的内存缓存功能,内存缓存的技术主要是一个使用的就是LruCache算法,另一个使用的就是弱引用
磁盘缓存:
DiskCacheStrategy.NONE: 表示不缓存任何内容。
DiskCacheStrategy.SOURCE: 表示只缓存原始图片。
DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。
DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
硬盘缓存的实现也是使用的LruCache算法
GreenDao
是ORM框架,是关系型数据库,数据库与对象之间做一个映射,不用写SQL语句,重心放在业务逻辑上。
优点:性能好,易用性比较强,轻量最小的内存消耗,小于100kb的数据库
使用方法:
1.某实体类-----》某表----->@Entity注解 @Id(autoincrement=true)
Make Project--》@Generated 生成构造参数和对应的get和set方法,同时会生成一个对应的greendao文件夹会生成与这个对应的三个类
某Dao--------》数据库访问对象(某表的操作)---->
DaoMaster-----》数据库的连接对象
DaoSession----》由连接生成的对话
插入insert重载的方法很多单个集合替换某一个都可以实现
查询queryBuilder()返回QueryBuilder对象可以对数据进行排序
Query.where(字段.eq())依然可以对其排序
删除数据delete(数据)
修改数据update(数据)修改和删除之后可以在onResume()重新获取一下数据
在获取数据的时候获取有密码的数据库
1.需要搭建NDK的开发环境
2.编译so文件 在activty里面加载第三方库也就是so文件
3.java调用本地方法获取c文件的内容(cpp文件夹下)(注意包名要一致)
手机的架构x86 arm64
6.0危险权限需要动态申请
7.0
1文件访问权限
1、首先要在Manifest中注册provider:、
2、android:resource的值是自定义的一个xml文件,里面指定了可以访问的目录
2、PopupWindow在Android7.0系统中显示位置错误:
3、APK signature scheme V2(建议打包V1和V2都勾选)
8.0
1、需要添加权限:
2、通知栏显示(android 8.0以后必须设置通知渠道id否则通知无法显示)
9.0 Android9.0不能加载http的url;
10.0 Android10.0不能获取到设备的IMEI
1.1、当首次安装应用时生成一个UUID,将此uuid存到手机存储中,而不是使用SharedPreferences存储,将此uuid上传至服务器进行存储。(缺点:用户手动删除此存储、重置手机那就唯一标识失效了)
1.2、使用ANDROID_ID标识(Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);)
缺点:重置手机失效,Android厂商特制系统不同设备拥有相同ANDROID_ID,或者获取ANDROID_ID为空;
1.3、使用极光推送、阿里推送等推送sdk获取它们的DeviceId作为设备唯一标识;
组件化:
插件化:
DexClassLoader classLoader=new DexClassLoader(”apk的目录“,getCacheDir.getPath(),null,null);
获取classLoader经过反射之后获取apk里面的方法
dex: 普通的dex
Odex:Optimized Dex 优化的Dex