- 问题:
看起来MVVM很好地解决了MVC和MVP的不足,但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能数据问题导致,也有可能业务逻辑中对视图属性的修改导致
以登录为例,登录时只需要拿着用户名和密码请求服务器即可
-
MVC中,需要先找到输入框,再从输入框中拿到用户名和密码,再进行登录操作
-
MVP中,通过Presenter拿到用户名和密码,进行登录。相当于通过引入了Presenter将M层和V层分离,降低耦合
-
MVVM中,用户在输入框输入完用户名和密码后,这种UI的变化直接同步到数据,直接登录
3.策略设计模式
========
适用场景: 某些业务中,某一个行为,会有多个实现类,并且当前业务只会选择一种实现类
4.Double Check Lock 实现单例
========================
public static TestInstance getInstance(){ //1
if (mInstance == null){ //2
synchronized (TestInstance.class){ //3
if (mInstance == null){ //4
mInstance = new TestInstance(); //5
}
}
}
return mInstance;
}
第一层判断主要是为了避免不必要的同步
第二层的判断则是为了在 null 的情况下创建实例。mInstance = new TestInstance(); 这个步骤,其实在jvm里面的执行分为三步:
1.在堆内存开辟内存空间;
2.初始化对象;
3.把对象指向堆内存空间;
由于在 JDK 1.5 以前 Java 编译器允许处理器乱序执行。不过在 JDK 1.5 之后,官方也发现了这个问题,故而具体化了 volatile ,即在 JDK 1.6 以后,只要定义为 private volatile static DaoManager3 sinstance ; 就可解决 DCL 失效问题
5.OkHttp中的责任链
=============
public interface Interceptor {
//每一层的拦截器接口,需要进行实现 Chain:串连拦截器的链
Response intercept(Chain chain) throws IOException;
//链主要有两个方法:拿到Request;通过Request拿到Response
interface Chain {
Request request();
Response proceed(Request request):Response throws IOException;//负责往下执行
}
}
链
public class RealInterceptorChain implements Interceptor.Chain {
final List interceptors;//节点的列表
final int index;//当前节点的index,通过index和interceptors就可以拿到所有节点
final Request request;//请求
public RealInterceptorChain(List interceptors, int index, Request request){
this.interceptors = interceptors;
this.index = index;
this.request = request;
}
@Override
public Request request() {
return request;
}
@Override
public Response proceed(Request request) throws IOException {
RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
//next传到当前节点,当前节点处理好request后就可以通过next执行proceed方法,将request传递到下一节点
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
}
拦截器
public class BridgeInterceptor implements Interceptor{
@Override
public Response intercept(Chain chain) throws IOException {
Log.e(“TAG”,“BridgeInterceptor”);
Request request = chain.request();
// 添加一些请求头
request.header(“Connection”,“keep-alive”);
// 做一些其他处理
if(request.requestBody()!=null){
RequestBody requestBody = request.requestBody();
request.header(“Content-Type”,requestBody.getContentType());
request.header(“Content-Length”,Long.toString(requestBody.getContentLength()));
}
Response response = chain.proceed(request);//这里的chain就是传进来的next,next的index已经加1
return response;
}
}
RealCall中excute()方法
protected void execute() {
final Request request = orignalRequest;
try {
List interceptors = new ArrayList<>();
interceptors.add(new BridgeInterceptor());
interceptors.add(new CacheInterceptor());
interceptors.add(new CallServerInterceptor());
Interceptor.Chain chain = new RealInterceptorChain(interceptors,0,orignalRequest);
Response response = chain.proceed(request);
callback.onResponse(RealCall.this,response);
} catch (IOException e) {
callback.onFailure(RealCall.this,e);
}
}
算法
1.反转单链表
=======
class Node{
private int data;
private Node next;
public Node(int data,Node next){
this.data=data;
this.next=next;
}
}
Node node4 = new Node(4, null);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node node1 = new Node(1, node2);
Node pHead = node1;//头结点
这组链表从1到4排序,要求反转后4到1
public static Node reverseList(Node pHead) {
Node pReversedHead = null; //反转过后的单链表存储头结点
Node pNode = pHead; //当前节点
Node pPrev = null; //前一结点
while (pNode != null) {
//1.记录next,下一步:更新当前节点的上一节点和本身。最后移动一位
Node pNext = pNode.next;
if (pNext == null) {
//到了尾节点
pReversedHead = pNode;
}
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
//递归方式反转(node1->node2->node3->node4->node5)
public static ListNode reverseR(Node head){
//空链表和一个结点的链表无需反转
if(head == null || head.next == null){
return head;
}
//递归到node4(head)时回溯时,reverseR(node4.next)直接返回node5
Node res = reverseR(head.next);
//递归回溯时,此时head指向node4,将node4的next(node5)的next指向node4(head)
head.next.next = head;
//将node4.next指向null
head.next = null;
return res;
}
输出
pHead = reverseList(pHead);//反转之后头结点
尾声
评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。
有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。
一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!