【AIDL和安卓代码架构】

每日总结

对每天的学习以及复习内容进行总结

JAVA基础知识

基本数据
数据类型 默认值 大小
boolean false 1比特
char ‘\u0000’ 2字节
byte 0 1字节
short 0 2字节
int 0 4字节
long 0L 8字节
float 0.0f 4字节
double 0.0 8字节
JAVA与C++的对比:

  • 都是面向对象的语言,都支持封装,继承,多态
  • Java不提供指针来直接管理内存,更加安全
  • Java存在垃圾回收机制来自动回收内存,不需要手动释放内存
  • Java单继承,多接口,但是C++有多继承
    Java常用集合
    常用集合(容器):
    List:ArrayList、LinkedList、Vector、Stack
    ArrayList:底层是数组,数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍;查找元素快、增删元素慢
    LinkedList:双向链表,查找元素慢、 增删元素快
    Vector:底层Object数组,线程安全,效率低,加了Sychorized关键字修饰
    Iterator:中有两个方法,next和hasNext
    Stack:先进后出的数据结构,不允许有遍历行为;栈不支持迭代器
    Set:HashSet、TreeSet
    **HashSet:**由哈希表支持,不保证set的迭代顺序,并允许使用一个null元素。基于HashMap实现,API也是对HashMap的行为进行了封装
    **TreeSet:**底层实际上是一个TreeMap,而TreeMap集合底层是一个二叉树;无序不可重复,但是可以按照元素的大小顺序自动排序
    Map:HashMap、TreeMap
    **HashMap:**由数组+链表的形式存储数据,基于哈希表的Map接口的非同步实现,允许使用null值和null键;底层使用数组实现,进行数组扩容需要重新计算扩容后每个元素在数组中的位置,很耗性能
    **TreeMap:**底层是基于红黑树实现的,基于key有序的key value散列表

Hashtable:基于哈希表的Map接口的同步实现,不允许使用null值和null键,底层数组实现,数组中每一项是个单链表,即数组和链表的结合体;synchronized是针对整张Hash表的,即每次锁住整张表让线程独占
ConcurrentHashMap:允许多个修改操作并发进行,其关键在于使用了锁分离技术,只要多个并发发生在不同的段上,它们就可以并发进行;ConcurrentHashMap使用多个子Hash表,也就是段,允许多个读操作并发进行,读操作并不需要加锁
**LinkedHashMap:**继承于HashMap,底层使用哈希表和双向链表来保存所有元素,并且它是非同步,允许使用null值和null键
LinkedHashSet:继承于HashSet、又基于LinkedHashMap来实现的。LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同。
List,Set,Map之间的区别

  • List:List在Java中有序,元素值可以重复,
  • Set:Set可以存储唯一,无序的对象
  • Map:存储键值对,多个key可以存储相同的值,但是key不能重复
    ArrayList与LinkedList的区别
  • ArrayList和LinkedList都是不同步的,也就是不保证线程安全
  • ArrayList底层使用Object数组,LinkedList底层使用双向链表
  • ArrayList采用数组存储,所以插入和删除元素时的时间复杂度受元素位置影响,LinkedList使用链表存储,所以,插入和删除元素时不受元素位置的影响
  • LinkedList不支持快速随机访问,ArryList支持
  • ArraryList的空间浪费主要体现在在list的链表的结尾会预留空间,LinkedList空间体现在它的每一个元素需要比ArraryList更多的空间
    Array和ArrayList的区别
    Array可以容纳基本类型和对象;而ArrayList只能容纳对象
    Array是指定大小的;而ArrayList可自动扩容
    Array没有提供ArrayList那么多方法列表,多维数组更适合用Array
    ArraryList和vector的区别?为什么要用ArraryList代替Vector
    Vector的所有方法都是同步的,可以多线程安全访问vector对象,单线程访问vector对象,会比较耗费时间。
    ArraryList是不同步的,所以在不需要保证线程安全时使用它
    HashMap和HashTable的区别
    HashMap是非线程安全的,HashTable是线程安全的,HashTable内部的方法都经过synchronized修饰
    HashMap的效率比HashTable要高,因为线程安全的问题
    HashMap中,null值可以作为键,这样的键只能有一个,可以有一个或多个键对应的值为null。但是在HashTable中只要有一个null,就抛出异常
    创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍
    JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable则 没有这样的机制
    HashMap和HashSet的区别
    HashSet 底层就是基于 HashMap 实现的
    ConcurrentHashMap 和 Hashtable 的区别
    JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。
    Hashtable 和 JDK1.8 之前HashMap 的底层数据结构类似都是采用 数组+链表
    在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。
    JDK1.8直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作
    Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下
    JAVA创建线程的4种方式:
  • 直接继承Thread类,重写run方法,使用 Thread类对象的start()开启线程
  • 实现runnable接口,将此实现类作为参数传递到 Thread类的构造器中,创建 Thread类的对象
  • 创建一个实现 Callable接口的实现类​​​​​​​, 将此 Callable接口实现类的对象作为参数传递到 FutureTask构造器中,创建 FutureTask对象,将 FutureTask的对象作为参数传递到 Thread类的构造器中,创建 Thread对象,并调用 start()
  • 从线程池里面获取

探究安卓里面的设计模式

1.观察者模式(Observer Pattern)
使用场景:
BroadCast监听系统广播或者程序内部自己发送的广播
EventBus 广播原理一样
LiveData 数据更新通知观察者
Adapter 中数据变化时,notifyDataSetChange
2.适配器模式(Adapter Pattern)
把一个类的接口转换为另一个类期待的接口类型,从而是接口不匹配的两个类兼容工作ListView RecycleView使用适配器模式,通过创建适配器,让数据正确的供RecycleView使用
3.代理模式(Proxy Pattern)
为当前类提供一个代理类给其他类访问,以防止当前类直接暴露出去。
Activity的管理者是ActivityManager,但最终的管理者为ActivityManagerService(AMS),在Android7.0及以前版本中, ActivityManager通过调用ActivityManagerProxy进行一些操作,而ActivityManagerProxy会调用AMS,真正的工作是由AMS来完成的。
4.工厂模式(Factory Pattern)
给外部提供一个统一创建特定对象的类,降低创建对象的复杂性。
Android中的BitmapFactory支持用不同的方式创建Bitmap对象。
5.单例模式(Singleton Pattern)
进程中只创建一个实例。Android8.0以上版本,IActivityManager和IActivityTaskManager实例都是单例,使用了系统的单例实现,
6.责任链模式
一条请求沿着一条链挨个儿传递,直到有对象处理它为止。
Android中UI事件传递使用了责任链模式
OkHttp的拦截器也是使用责任链模式
7.建造者模式(Builder Pattern)
将一个复杂对象的创建和表示分离,使用相同的构建过程创建不同的对象。
AlertDialog使用了建造者模式。

内存泄漏的案例: 可在app里面集成LeakGanary检查内存泄漏
在进行异步操作时,我们经常会使用到Handler类。常见的写法如下。
public class MainActivity extends Activity { … private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { } }; }
当使用内部类或匿名内部类的方式创建Handler时,Handler对象会隐式地持有一个外部类对象的引用(这里的外部类是Activity)。一般在一个耗时任务中会开启一个子线程,如网络请求或文件读写操作,我们会使用到Handler对象。但是,如果在任务未执行完时,Activity被关闭了,Activity已不再使用,此时由GC来回收掉Activity对象。由于子线程未执行完毕,子线程持有Handler的引用,而Handler又持有Activity的引用,这样直接导致Activity对象无法被GC回收,即出现内存泄漏。

解决方法主要在于两点:
​1.将Handler声明为静态内部类。​因为静态内部类不会持有外部类的引用,所以不会导致外部类实例出现内存泄露。
​2.在Handler中添加对外部Activity的弱引用。​由于Handler被声明为静态内部类,不再持有外部类对象的引用,导致无法在handleMessage()中操作Activity中的对象,所以需要在Handler中增加一个对Activity的弱引用。

public class MainActivity extends Activity {  
    private final MyHandler mHandler = new MyHandler(this);  

    private static class MyHandler extends Handler {  
        private final WeakReference<MainActivity> mActivity;  

        public MyHandler(MainActivity activity) {  
            this.mActivity = new WeakReference<MainActivity>(activity);  
        }  

        @Override  
        public void handleMessage(Message msg) {  
            MainActivity mainActivity = mActivity.get();  
            if (mainActivity == null) {  
                return;  
            }  
            // your code here  
        }  
    }  
} 

关于WeakReference的说明:
WeakReference即弱引用,与强引用(即我们常说的“引用”)相对。它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向,该对象就会在被GC检查到时回收掉。
对于上面在子线程中下载文件的示例代码,改为采用WeakReference之后,如果任务未执行完但是用户却关闭了MainActivity,但由于仅有一个来自MyHandler的弱引用指向MainActivity,所以GC仍然会在检查时把MainActivity回收掉。这样,内存泄露的问题就不会出现了。
两种单例模式

//   饿汉单例
public final class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
        return instance;
    }
}
//   懒汉单例
public class Singleton {
    private  static Singleton instance;
    private  static  final Object syn = new Object();

    private Singleton() {
    }

    public static Singleton getInstance(){
        if (instance == null){
            synchronized (syn){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

探究AIDL

安卓官网对于AIDL的介绍:https://developer.android.google.cn/guide/components/aidl?hl=zh_cn
主要参考: https://juejin.cn/post/6844903496882323464
服务端 :创建了一个service,并在service内部声明了一个IBinder对象,它是一个匿名实现的IMyAidlInterface.Stub的实例
客户端 : 将服务器端的aidl拷贝到客户端,这边特别要注意,拷贝后的客户端的aidl文件包目录必须与服务器端保持一致,拷贝完后同样时编译工程,让客户端也生成对应的java文件.绑定完服务,就是进行调用
AIDL生成的Java文件:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
// Declare any non-default types here with import statements

public interface IMyAidlInterface extends android.os.IInterface
{
  /** Default implementation for IMyAidlInterface. */
  public static class Default implements com.example.aidlserver.IMyAidlInterface
  {
    /**
              * 自己添加的方法
              */
    @Override public int add(int value1, int value2) throws android.os.RemoteException
    {
      return 0;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.example.aidlserver.IMyAidlInterface
  {
    private static final String DESCRIPTOR = "com.example.aidlserver.IMyAidlInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.example.aidlserver.IMyAidlInterface interface,
     * generating a proxy if needed.
     */
    public static com.example.aidlserver.IMyAidlInterface asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.aidlserver.IMyAidlInterface))) {
        return ((com.example.aidlserver.IMyAidlInterface)iin);
      }
      return new com.example.aidlserver.IMyAidlInterface.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    {
      String descriptor = DESCRIPTOR;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_add:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          int _arg1;
          _arg1 = data.readInt();
          int _result = this.add(_arg0, _arg1);
          reply.writeNoException();
          reply.writeInt(_result);
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.example.aidlserver.IMyAidlInterface
    {
      private android.os.IBinder mRemote;
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public android.os.IBinder asBinder()
      {
        return mRemote;
      }
      public String getInterfaceDescriptor()
      {
        return DESCRIPTOR;
      }
      /**
                * 自己添加的方法
                */
      @Override public int add(int value1, int value2) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        int _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeInt(value1);
          _data.writeInt(value2);
          boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().add(value1, value2);
          }
          _reply.readException();
          _result = _reply.readInt();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      public static com.example.aidlserver.IMyAidlInterface sDefaultImpl;
    }
    static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    public static boolean setDefaultImpl(com.example.aidlserver.IMyAidlInterface impl) {
      // Only one user of this interface can use this function
      // at a time. This is a heuristic to detect if two different
      // users in the same process use this function.
      if (Proxy.sDefaultImpl != null) {
        throw new IllegalStateException("setDefaultImpl() called twice");
      }
      if (impl != null) {
        Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.example.aidlserver.IMyAidlInterface getDefaultImpl() {
      return Proxy.sDefaultImpl;
    }
  }
  /**
            * 自己添加的方法
            */
  public int add(int value1, int value2) throws android.os.RemoteException;
}

Stub的目录结构也不复杂,一个构造函数,一个asInterface方法,一个asBinder方法,一个onTransact方法,一个Proxy代理类,这边Proxy与Stub同时实现了我们定义的aidl,且Proxy中实现了我们在aidl中定义的add/addUser方法。​ 在客户端,我们绑定服务的时候通过Stub.asInterface()返回aidl对象,查看asInterface源码,我们不难发现,客户端获取到的其实时Stub.Proxy,一个远程服务的代理。所以客户端调用add/addUser方法其实调用的时Stub.Proxy中实现的add/addUser,在Stub.Proxy中我们可以看到一句核心代码mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); 追溯源头,mRemote其实就是IMyAidlInterface.Stub,随着mRemote.transact传递到了IMyAidlInterface.Stub.onTransact, onTransact中执行了add/addUser,回调到了我们在服务端定义Service中声明IBidner时重写的add/addUser,这就是AIDL的整个流程。

安卓代码架构(MVC,MVVM,MVP)

主要参考: https://juejin.cn/post/6997295828079476772
这三种架构的目的都是分离,避免将过多的逻辑全部堆积在一个类中
MVC架构: MVC是模型(Model)-视图(View)-控制器(Controller)的缩写,用一种业务逻辑、数据、界面显示分离的方法组织代码。其实Android Studio创建一个项目的模式就是一个简化的mvc模式。
Model:实体类(数据的获取、存储、数据状态变化)。
View:布局文件
Controller:Activity(处理数据、业务和UI)。

MVP架构: Activity类的职责不断增加,以致变得庞大臃肿
MVP是MVC架构的一个演化版,全称是Model-View-Presenter。将MVC中的V和C结合生成MVP中的V,引入新的伙伴Presenter。
Model:实体类(数据的获取、存储、数据状态变化)。
View:布局文件+Activity。
Presenter:中介,负责完成View与Model间的交互和业务逻辑。

MVVM架构: 是 Model-View-ViewModel 的简写。MVVM与MVP的结构还是很相似的,就是将Presenter升级为ViewModel。在MVVM中,View层和Model层进行了双向绑定(即Data Binding),所以Model数据的更改会表现在View上,反之亦然。ViewModel就是用来根据具体情况处理View或Model的变化。
Model:实体类(数据的获取、存储、数据状态变化)。
View:布局文件+Activity。
ViewModel: 关联层,将Model和View进行绑定,Model或View更改时,实时刷新对方。

/frameworks/base/core/res/res/values/config.xml是framework层的配置文件。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值