金三银四那些事(三)

作者: 的一幕 | 来源:发表于2018-04-25 11:26 被阅读69次

    说说你对android中设计模式的认识:

    单例模式
    这里会考到手写一个单例模式:

    public class Singleton {
        private static volatile Singleton instance = null;
    
        private Singleton(){
        }
     
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    上面有两层的非空判断,一般这里会问到,第一层是为了防止多次加锁的判断,因为同步锁是耗时的,所以只在首次为空的时候,只进行一次加锁,第二次纯粹是为了new对象的时候非空判断。

    android中用到的单例模式举例:
    Android-Universal-Image-Loader中的单例

    private volatile static ImageLoader instance;
    /** Returns singleton class instance */
    public static ImageLoader getInstance() {
        if (instance == null) {
            synchronized (ImageLoader.class) {
                if (instance == null) {
                    instance = new ImageLoader();
                }
            }
        }
        return instance;
    }
    

    builder模式
    将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

    public class Person {
        private String name;
        private int age;
        private double height;
        private double weight;
        //构造函数私有化
        private Person(Builder builder) {
            this.name=builder.name;
            this.age=builder.age;
            this.height=builder.height;
            this.weight=builder.weight;
        }
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public double getHeight() {
            return height;
        }
    
        public void setHeight(double height) {
            this.height = height;
        }
    
        public double getWeight() {
            return weight;
        }
    
        public void setWeight(double weight) {
            this.weight = weight;
        }
    
        static class Builder{
            private String name;
            private int age;
            private double height;
            private double weight;
            public Builder name(String name){
                this.name=name;
                return this;
            }
            public Builder age(int age){
                this.age=age;
                return this;
            }
            public Builder height(double height){
                this.height=height;
                return this;
            }
    
            public Builder weight(double weight){
                this.weight=weight;
                return this;
            }
            //builder静态内部类里面定义一个方法来生成外部类的私有构造器
            public Person build(){
                return new Person(this);
            }
        }
    }
    

    调用部分:

    Person.Builder builder=new Person.Builder();
    Person person=builder
            .name("张三")
            .age(18)
            .height(178.5)
            .weight(67.4)
            .build();
    

    android源码部分builder设计模式举例:
    AlertDialog.BuilderGsonBuilder
    总结:

    • 定义一个静态内部类Builder,内部的成员变量和外部类一样
    • Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
    • Builder类提供一个build方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有构造函数,该构造函数的参数就是内部类Builder
    • 外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的值

    观察者模式
    定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新

    • 观察者,我们称它为Observer,有时候我们也称它为订阅者,即Subscriber
    • 被观察者,我们称它为Observable,即可以被观察的东西,有时候还会称之为主题,即Subject

    其实咱们在listview中刷新列表的时候,会用到adapter的notifyDataSetChanged方法,其实这里也是一个观察者模式,咱们去BaseAdapter中去找找该方法:

    private final DataSetObservable mDataSetObservable = new DataSetObservable();
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
    

    接着看DataSetObservable中notifyChanged方法:

    public void notifyChanged() {
        synchronized(mObservers) {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
    

    可以看到这里遍历了mObservers集合,然后调用了onChanged方法。只能去父类找找mObservers是个什么玩意。

    DataSetObservable的父类.png
    从这里可以看出来实际是被观察者类,其中咋们要观察的对象是DataSetObserver,也就是我们的观察者。所以说这里的观察者一旦被触发了,会调用到自己的onChanged方法。
    那是什么registerDataSetObserver的呢,接着看listview的源码部分:
    image.png
    那看看AdapterDataSetObserver该观察者中onChange方法都做了些啥:
    @Override
    public void onChanged() {
         mDataChanged = true;
         mOldItemCount = mItemCount;
         mItemCount = getAdapter().getCount();
    
         // Detect the case where a cursor that was previously invalidated has
         // been repopulated with new data.
         if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                && mOldItemCount == 0 && mItemCount > 0) {
             AdapterView.this.onRestoreInstanceState(mInstanceState);
             mInstanceState = null;
         } else {
            rememberSyncState();
         }
         checkFocus();
         requestLayout();    //onChanged的主要目的就是重布局
    }
    

    其实从最后一行调用的方法可以看出来,onChange里面做的工作就是刷新listView中整体的布局。这会知道了调用adapter.notifyDataSetChanged方法就是刷新listview列表了吧。
    总结下来观察者模式实际可以用一张图说明:

    观察者模型图.png

    后面的原型模式策略模式请点击这里

    mvc和mvp的对比:

    • activity或fragment的职责不同
      在mvc中activity充当controller层,但也脱不了view层的,但在mvp中activity完全是充当了view层的,只和view相关的代码。这也是为什么mvc过渡到mvp的好处,这里activity没有像在mvc中那么臃肿。
    • view层不同
      在mvc中view层主要是一些layout资源文件,再就是一些自定义的view了。其实这里看得出来这里的view层发挥的功能很小,毕竟不像web开发那样。在mvp中view层指的是activity或fragment,这里缺陷是随着业务复杂,activity或fragment也会变得复杂。
    • 控制层不同
      mvc中controller层指的是activity或是fragment,但是大家也知道这里的activity或fragment又有view层的影子,毕竟activity又需要处理一些控件啥的。在mvp中controller层就是单一的p层了,简单地建立了view层和model层的桥梁。
    • 关系链不同
      在mvc中view层和model层直接联系的,比如我们的自定义view需要些数据展示页面的时候,就直接从model层去取的;也会出现model层获取到数据后,直接到view层刷新数据了,因此这里会出现直接交互的关系链。而在mvp中view和model层完全是通过p层来建立联系的,不再持有对方的引用,引用都在p层了。
    • 交互方式不同
      MVP中通讯交互基本都是通过接口的,MVC中的通讯交互很多时候都是实打实的调用对象的方法,简单粗暴!
    • 实现方式不同
      MVC和MVP的Model几乎一样的,都是处理数据,只要不在Activity或者Fragment中请求数据,其他的所有控制都放在Activity或者Fragment中,这样写就基本是MVC的模式,这样写不麻烦,但是很容易把Activity写出上万行代码。用MVP的时候我们需要写很多View和Presenter接口来实现模块之间的通讯,会增加很多类。

    画出mvp的umm图:

    这里以登录模块为例:


    mvp中登录uml图.png

    说说mvvm的使用:

    说说你对android中三级缓存的理解:

    整个过程是先从内存缓存中找数据,如果内存缓存中没数据,到文件缓存中找,如果再没有去网络中找数据,网络中数据加载回来后,将数据保存到文件缓存中,再加载到内存中。
    内存缓存:
    主要用到android定义好的LruCache对象,此时需要传一个允许内存缓存的大小,一般遵循:

    int maxMemory = (int) Runtime.getRuntime().maxMemory();
    int cacheSize = maxMemory / 8;
    

    这里会考到LruCache内存缓存的算法,这里的算法是最不经常使用的数据优先被移除,主要涉及到LinkedHashMap的数据结构问题。
    文件缓存
    这里存的时候,首先将url用MD5的encode过程,然后得到文件的name,然后通过定义的file_path目录得到File对象,得到file之后判断是不是已经存在该file的parentFile,如果不存在需要创建该file的parentFile。最后得到该file的输出流,最后使用bitmap.compress保存到本地文件中。
    服务端缓存
    这个就没什么好说的了,使用HttpURLConnection对象获取到bitmap的输入流,最后使用BitmapFactory.decodeStream得到bitmap对象。

    说说LinkedhashMap的数据结构:

    里面是一个双向链表的数据结构,维护着一个双重链接列表的顺序。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。该迭代顺序遵循的原则如下:

    • 第一种和队列一样默认是按插入顺序排序,先进来的是最老的元素,放在队头,将来会被先移出去,最后进来的是新的元素。
    • 第二种,基于访问排序,那么调用get方法后,会将每次访问的元素移至队尾,将来移除的时候移除的是队头,最先访问的元素最后才被移除,不断访问可以形成按访问顺序排序的链表。

    java反射的机制:

    HTTP网络的工作流程:

    1.建立TCP连接
    2.web浏览器向web服务器发送请求命令
    3.web浏览器发送请求头信息
    4.web服务器应答
    5.web服务器发送应答头信息
    6.web服务器向浏览器发送数据
    7.web服务器关闭TCP连接

    Http请求头都有哪些

    image.png

    TCP对比UDP来说都有哪些:

    TCP的三次握手,四次挥手指的什么:

    TCP的三次握手:

    • 第一次握手:
      建立连接,客户端A发送SYN=j包(这里表示新连接的一个标志位)到服务器B,并进入SYN_SEND状态,等待服务器B确认
    • 第二次握手:
      服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1,这里表示收到了来自A客户的应 答),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态
    • 第三次握手:
      客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
      TCP的四次挥手:
    • 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
    • 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
    • 服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
    • 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。

    kolin学习:

    说说你看过哪些框架的源码:

    相关文章

      网友评论

        本文标题:金三银四那些事(三)

        本文链接:https://www.haomeiwen.com/subject/fdmelftx.html