• 准备


      一、Android 基础面试  https://www.jianshu.com/p/ffe7e0561c85?tdsourcetag=s_pcqq_aiomsg(还需要总结知识)

                 https://blog.csdn.net/songzi1228/article/details/99975018  (多线程的总结)

                  https://www.jianshu.com/p/90db19b4c98a   (大佬的博客园来观看使用)

      1.Activity异常的生命周期处理  

      @Override
      public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
    super.onSaveInstanceState(outState, outPersistentState);
      }

      @Override
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
      }
      异常或者系统内存不足会调用该方法

      2.Fragment的生命周期
     
     

          

                 Fragment的生命周期

      3.SingleTask的启动模式

       

        可以将不同的APP的activity中设置为相同的taskAffinity,虽然在两个应用当中但是他们会被分配到同一个Task中

      4. View的事件分发机制

        

      

      二、异步消息处理机制

      1. 主线程中调用Loop,那么为什么没有造成阻塞呢?
       ActivityThread的Main方法里面有个Loop的消息队列,ActivityThread 有个 getHandler 方法,得到这个 handler 就可以发送消息,然后 loop 里就分发消息,然后就发给 handler,

       然后就执行到 H(Handler )里的对应代码。所以说ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的程序也就可以退出了,所以这些代码就不会卡死。

      2. AsyncTask

        1). 组成:线程池+Handler

       2). Sting : 指的是doInBackgroud的参数类型  

        String : 指的是onProgressUpdate的参数类型

        Long : 指的是onPostExecute的方法的参数以及doInBackground的返回参数

      public class AsynctaskText extends AsyncTask<String , String , Long>{
      /**
      * 运行在UI线程中,在调用doInBackground之前运行的,可以做一些控件初始化
      */
      @Override
      protected void onPreExecute() {
      super.onPreExecute();
      }

      /**
      *后台运行的方法,运行在非ui线程中,可以执行耗时操作
      */

      @Override
      protected Long doInBackground(String... strings) {
      return null;
      }

      /**
      *doBackground里面会执行onProgressUpdate这个函数
      */

      @Override
      protected void onProgressUpdate(String... values) {
      super.onProgressUpdate(values);
      }


      /**
      *运行在ui线程,在doInBackground之后去执行的,
      */


      @Override
      protected void onPostExecute(Long integer) {
      super.onPostExecute(integer);
      }

      @Override
      protected void onCancelled() {
      super.onCancelled();
      }
     }

       execute和executeOnExecutor的区别

      execute :  Execute方法是串行执行,需要一个一个去执行

      executeOnExecutor  :  并行执行,需要添加线程池参数, 任务可以同步进行

      

     三、VIew绘制相关知识

      1. window、surface、decorview

       

       window :  是对我们Android系统当中窗口的一种抽象类,PhoneWindow是Window窗口的一个实现类。

       DecorView : 是我们应用窗口的一个根容器(本质上是一个FreamLayout),主要包含两个参数TitleView 和 ContentView

       surface :  是窗口独占一个surface的写实区域

       3. ListView滑动时候为什么不会发生OOM的原因(RecycleBin的机制) : 将离开屏幕外的view删除并且存放到RecycleBin这个类里面,当准备展示下一个view的时候,它会从RecycleBin里面取出一个scrapView,然后就将它设置为converVIew的参数进行判断是否已经设置过,从getView里面有这个方法从而到达view复用的作用

       4.ListView的性能优化5个优化点:

        1). converView

        2).viewHolder

        3).getVIew尽量少做耗时的操作(当滑动停止时候再去加载图片)

        4).ListVIew中的item元素避免半透明

        5).开启硬件加速

      四、 异常与性能

       1. 如何产生ANR

        a). View的按键或者触摸事件在5秒没有得到回应

        b). BroadcastReciver的onReceive()函数运行在了主线程中,在10秒内无法完成处理    

        c).Service的各个生命周期函数在20秒内无法完成处理

      2. 如何解决ANR

        a). 使用AsyncTask处理IO的耗时操作

        b). 使用Thread或者HandlerThread提供异步操作

        c). 使用Handler来处理工作线程的耗时操作

        d). Activity里面的所有生命周期都是在主线程中,避免写大量的耗时操作

      3. OOM容易混淆的概念

       内存溢出:我们申请的内存已经超出虚拟机的最大内存的限度就会抛出Out  Of  memory

       内存抖动 :  短时间大量的对象被创建然后就释放,触发的GC机制,严重占用内存区。

       内存泄露 :  我们要回收的对象无法进行GC的回收操作

      4. bitmap的讲解

       (1).Bitmap的模型: Android 2.3.3之前,Bitmap的像素数据存放在Native内存,而Bitmap对象本身则存放在Dalvik Heap中。而在Android3.0之后,Bitmap的像素数据也被放在了Dalvik Heap中。

       (2).在Android2.3.3之前推荐使用Bitmap.recycle()方法进行Bitmap的内存回收; 在Android3.0之后更注重对Bitmap的复用

       (3). recycle 的方法:  它既回收JAVA的内存也回收native的内存,这个对象以后就不会再被调用了。当你没有对象时候就会有GC去回收它,建议不要主动去调用它(快速截屏)

       (4).inBitmap参数的好处 : 前提是旧的inBitmap大小>=新的inBitmap的大小,否则不能复用。

       (5). LRU的算法 :  内部使用LinkedHashMap作为缓存, get和put完成添加和获取的操作,HashMap的remove方法来移除对象,当内部缓存满的时候,会调用trimToSize把较早或者使用最少的缓存对象移除出去,添加新的对象。

       (6). 三级缓存 :   网络->本地->内存

         原理:第一次打开app时候,图片首先从网络获得,然后再本地和内存各缓存一份,再去请求相同的url的时候,就会去本地或者内存去找  

       (7). 图片产生OOM的原因

         a.一个页面加载过多图片

           b. 加载图片没有进行对图片尺寸、质量进行压缩

         c.加载大量图片时候做图片缓存

         (8) . 图片的种类

         PNG : 无损压缩格式,支持透明通道

         JPEG : 有损压缩格式,不支持透明通道 

         WEBP : 既支持有损压缩也支持无损压缩,也支持透明通道

         GIF : 支持多帧动画

       (9). 超大图片加载方案
         可以使用BitMapRegionDecoder

      5. UI卡顿的讲解

        1). UI卡顿原因分析

         (1).在UI线程中做轻微的耗时操作,导致UI卡顿

         (2).布局Layout过于复杂,无法在16ms内完成渲染(从布局上),可以使用include、merage、view-stub这样标签作为处理,布局过于复杂使用自定义view

        (3).同一时间动画执行次数太多,导致CPU或GPU负载过重

        (4).View的过度绘制,导致某些像素在同一帧时间内过度绘制多次,从而让CPU或者GPU过重(从代码上) ----->自定义view使用clipRect来屏蔽被遮盖的view绘制

        (5).冗余的资源或者逻辑导致加载过慢

        (6).避免在onDraw里面执行对象的创建(这样会产生内存抖动)

        (7).图片显示(监听ListView滑动时候,就不要加载图片,当监听到停止时候,再去加载图片)

      6.常见内存泄露案例

       1.单例:长生命周期的对象(Application的对象)持有短生命周期的对象(是指Activity的对象)---->解决getApplicationContext()

       2. handler : 非静态内部类持有外部类的引用,导致于无法释放外部类的对象---->解决方法将handler至于为static的对象,然后将外部类改为弱引用来使用

       3.线程引起: AsyncTask和Runnable使用匿名内部类,因为非静态内部类持有外部类的引用,和handler类似

       4.文件的读写、数据库网络启用后没有关闭

       5.注册广播没有关闭广播

      7.内存管理

       (1).分配机制

       (2).回收机制

         五大进程:前台进程、可见进程服务进程、后台进程、空进程

       (3).内存优化

         当Service完成任务后,尽量停止它(可以使用IntentService)----->它是在异步线程中执行的,用完后它会自动释放对象的

        避免滥用Bitmap导致内存的浪费

        尽量少使用枚举常量,可以使用注解方法

        使用多进程来分担主内存耗时

      8.冷启动优化

       

     

      五、开源框架的学习

      1.AOP的切面编程(目前作为了解使用)

       (1).注解使用先关介绍

        @Before 前置通知,相当于BeforeAdvice

        @AfterReturning 后置通知,相当于AfterReturningAdvice

        @Around 环绕通知,相当于MethodInterceptor

        @AfterThrowing抛出通知,相当于ThrowAdvice

        @After 最终final通知,不管是否异常,该通知都会执行

        @DeclareParents 引介通知,相当于IntroductionInterceptor (了解)

       (2). JoinPoint 连接点对象可以获得参数讲解

    目标对象:getTarget()

    获得方法签名:getSignature()

    获得方法名称:getSignature().getName()

    获得实际参数:getArgs()

    获得当前指定方法的类型:getKind()

    案例1:性能监控

        @Aspect
       public class PerformanAop {
       @Around("call(* com.example.mi.okhttp.MainActivity.**(..))")
       public void getTime(ProceedingJoinPoint  joinPoint){
       Signature signature = joinPoint.getSignature();
       String name = signature.toShortString();
       long time = System.currentTimeMillis();
       try {
        joinPoint.proceed();             ----------------->执行该程序的方法
       } catch (Throwable throwable) {
        throwable.printStackTrace();
      }
        Log.d("ceshi", name + "=" + (System.currentTimeMillis() - time));
        }
      }  

     

    2.MVC的架构的介绍

     

     C层 : 页面和数据交互,耦合程度高,不利于解耦

     

    3.MVP的架构介绍

     

     MVP的特点:

     Presenter完全将ModelView解耦,主要逻辑处于Presenter中;Presenter和具体View没有直接关联,都是通过接口进行交互。

     View变更时候,可以保持Presenter不变,所以Model和View已经完全解耦

     MVP的优点:

     低耦合:Model、VIew层的变换不回影响到对方

     可重用性:Model层可用于多个View

     方便测试:可以单独多Model和VIew层单独测试

     MVP的缺点:

     当有一个很大的复杂页面,这样接口机会新增加很多接口,导致维护成本很大。

     解决方法:把一些通用的接口作为基类,其他接口去继承

     

    4.MVC和MVP流程的大致区别

     

     

    5.MVVM的数据模型

     

      

     MVVM的特点:

     ViewModel和Model/View进行双向绑定,View 发生改变时候,ViewModel会通知Model更新数据;Model数据更新时候,ViewModel会通知View更新显示

     

    6.插件化模型(学习反射)主要解决

      (1).动态加载       DexClassLoader、PathClassLoader学习(动态加载app)

      (2).动态加载资源文件   AssetManager 动态加载资源文件

      (3).代码的加载

     

    7.热修复模型

     (1).Android 类加载机制

      PathClassLoader  :  加载内存中已经安装的apk中的dex

     DexClassLoader :  加载sd卡中的apk/jar

     (2).热修复机制(通过向dexElements数组插入dex来完成热修复)

     dexElements数组、ClassLoader会遍历dexElements这个数组

     原理:dexElements数组会在基类的BaseClassLoader中创造好,DexClassLoader和PathClassLoade

     都是继承BaseClassLoader这个类的,通过ClassLoader去遍历dexElements数组,加载这个数组

     dex文件,如果BaseClassLoader加载到正确的dex文件后,就不会再去加载有crash的dex文件了,

     把正确的dex文件排在dexElements数组前面即可。

     

    8.进程保活的实现

     (1).Android的进程优先级:前台优先级、可见进程、服务进程、后台进程、空进程(主要为了做缓存、缩短下次启动时间)

     (2).进程保活方案

         a.利用系统广播拉活 

        缺点:当只有在特定场景下才可以拉起保活,下次被杀死后,无法得到控制

         b.利用系统Service机制拉活 :  onStartCommand方法,返回START_STICKY

             缺点:在短时间内被多次杀死就不会被拉活、被root或者其他工具被stop也是无法拉活的

      c.通过native进程拉活(通过AMS的进程杀死)

      d.进程相互唤醒(打开一个app同时唤醒另一个app)

      e.提升Service进程优先级,比如改为前台进程   startForeground(1,notification)

      f.JobScheduler用来检测你自己的服务是否被杀掉,如果被杀掉了,你重启自己的服务   缺点:需要有自启动权限

     

      六、Java基础面试

       1.synchronized(悲观锁)和lock的区别

         synchronzied 同步代码块底层原理 :  monitorenter指向同步代码块的开始位置,monitorexit指向同步代码块的结束位置  

         线程执行到monitorenter指令时,该线程对象持有锁,即线程获得monitor持有权,count计数器+1,获得线程锁

         线程执行完毕后,执行monitorexit执行指令,count为0,释放锁。   注意:无论是正常结束还是异常结束,都会执行monitorexit指令

         synchronized 的同步方法的底层原理 :  ACC_SYNCHRONIZED的flag标记该方法是否是同步方法,从而执行相应的同步调用

       2.sleep和wait(notify)区别

         sleep是Thread的内部的一个静态方法,可以再任何地方调用;wait是Object成员方法,只能在synchroized代码中被调用,其他地方调用会非法监控异常

         在等待时候,wait是释放锁的,用于线程交互;sleep会一直持有锁,不会改变锁的状态,用于线程切换cpu的状态

       3.lock、synchronized 和 volatile的区别

        synchronized 和 volatile 的区别

        volatile只能在线程内存和主内存之间存一个变量值,synchronized可以修饰类、对象、方法等,但是synchronized很消耗内存

        volatile的理解:具有可见性、有序性,不具备原子性、禁止指令重排。 volatile修饰的变量会强制把数值写入主内存中

        synchronized 和 lock 的区别

        synchronized是Java的关键字,Lock是接口

        synchronized是自动释放锁,Lock需要手动释放锁,所以写到try catch中并且在finally中释放锁

        synchronized无法中断等待的锁,Lock可以中断,它可以在激烈的读写操作   

           

       4.线程池工作流程:

        (1).首先判断线程池是否已经满了

        (2).其次是判断工作队列是否已经满了

        (3).最后判断整个线程池是否满了

        五种线程池、四种拒绝策略、三种阻塞队列

        五种线程池 

        threadPool = Executors.newCachedThreadPool();               //有缓冲的线程池,线程数 JVM 控制
        threadPool = Executors.newFixedThreadPool(3);                 //固定大小的线程池,支持线程池并发
        threadPool = Executors.newScheduledThreadPool(2);       //固定大小的线程池,支持定时或者周期执行任务
        threadPool = Executors.newSingleThreadExecutor();          //单线程的线程池,只有一个线程在工作
        threadPool = new ThreadPoolExecutor();                               //默认线程池,可控制参数比较多     

        四种拒绝策略

        rejected = new ThreadPoolExecutor.AbortPolicy();                //默认,队列满了丢任务抛出异常
        rejected = new ThreadPoolExecutor.DiscardPolicy();            //队列满了丢任务不异常
        rejected = new ThreadPoolExecutor.DiscardOldestPolicy();   //将最早进入队列的任务删,之后再尝试加入队列
        rejected = new ThreadPoolExecutor.CallerRunsPolicy();          //如果添加到线程池失败,那么主线程会自己去执行该任务

        三种阻塞队列

        有限队列

         ArrayBlockingQueue<>(5);                             //基于数组的先进先出队列,有界
         SynchronousQueue<>();                                //无缓冲的等待队列,无界     适用于newCachedThreadPool线程池

        无限队列

        LinkedBlockingQueue<>();                            //基于链表的先进先出队列,无界     适用于newFixedThreadPool、newScheduledThreadPool

        参数讲解:

        * corePoolSize:核心线程池大小

        * maximumPoolSize:最多线程池大小

         * keepAliveTime:表示空闲线程的存活时间

         * unit:keepAliveTime时间单位

         * workQueue:阻塞任务队列

        * threadFactory:新建线程工厂

        * RejectedExecutionHandler:保护策略

       5.throw和throws的区别

        throw :  用在方法体内,跟的是对象名,throw抛出异常,一定会抛出某种异常

        throws :  用在方法后面,跟的是类名,它抛出的异常只是一种可能性,并不一定会抛出异常的

       6.final、finalize、finally的关键字的区别

        final :  修饰符,可以修饰类,不能再派生新的子类也不能作为父类被继承 ; 可以修饰变量,该变量的数值就不能修改

        finally :  try ... catch 语句中使用

        finalize :  在垃圾回收时候使用,被清理对象没有被引用的情况下调用的。

       7.注解相关介绍

       1.Retention : 定义注解保留的时间
           RetentionPolicy.SOURCE 注解只保留在源码,在编译器进行编译时会被忽略
              RetentionPolicy.CLASS 注解由编译器保存在class文件中,但不需要在运行时由VM保留,无法通过反射读取,这是默认的策略。
           RetentionPolicy.RUNTIME 注解由编译器保存在class文件中,并在运行时由VM保留,可以通过反射读取。

          2.Target  : 修饰对象的范围
             ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
             ElementType.FIELD:允许作用在属性字段上
                   ElementType.METHOD:允许作用在方法上
                   ElementType.PARAMETER:允许作用在方法参数上
                   ElementType.CONSTRUCTOR:允许作用在构造器上
                   ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
                   ElementType.ANNOTATION_TYPE:允许作用在注解上
                   ElementType.PACKAGE:允许作用在包上

       8.触发GC的条件

        (1). 当应用程序空闲时,即没有应用线程再运行时,GC会被调用的

        (2). JAVA内存不足的时候,GC会被调用

       9. 减少GC的开销措施

        (1). 不要显示调用System.gc()

        (2).尽量减少创建临时对象(相当于减少垃圾的产生,从而延长第二次GC的触发时间),对象不用时候最好显示设置为null(有利于GC收集器判定垃圾,从而提高垃圾回收)

        (3). 尽量使用StringBuffer,而不用String来增加字符串

        (4). 能使用基本变量就不用封装好的对象(比如int ---> Integer对象)

        (5). 尽量减少使用静态变量(静态变量属于全变量,不会被GC回收掉,他们也会一直占用内存,增加GC的次数)

      10.终止线程的方法

        1.while(boolean 变量值去终止) ------> 但是不会被立即终止线程

        2.while(!Thread.interrupted())---------->判断是否执行Thread.interrupted这个方法,执行之后一定在try..catch..中的catch方法中执行return,这样才可以真正中断该方法

        3. while(flag && ! Thread.interrupted()) ----->这两个方法去真正执行中断程序 

                         private volatile boolean flag = false

      11.多线程优化
        将非UI线程设置线程等级,一般下载线程Thread.setThreadPriority(Processs.THREAD_PRIORITY_BACKGROUND);

      七、网络相关的知识

       1.http和https的区别 

        HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
                     HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
                     HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
                     HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。

       2. http1.0、http1.1和http2.0区别

         http1.0  1.0+ :  支持版本号、请求头、代理连接

         http1.1 :  默认持久连接、支持缓存、支持管道方法发送多个请求 (一个TCP只能连接一个HTTP,不能复用;只能单向请求方式)

         http2.0 :  支持多路复用,可以设定请求的优先级;支持双向通信;去除不需要的HTTP请求头,减少网络带宽

       3.Http的请求方式

        

        常见以下四种:

        get :  获取资源

        post : 创建资源

        put :   更新资源

        delete : 删除资源

       4.get和post的区别

        url可见性 :  get的url可见(不安全)    post的url参数不可见(安全)

        数据传输上 :  get通过拼接url进行传递参数       post通过body体传输参数

        缓存性: get请求是可以缓存的     post请求不可以缓存

        后退页面的反应 : get请求页面后退时,不产生影响            post请求页面后退时,会重新提交请求 

        传输数据的大小 :  get一般传输数据大小不超过2k-4k      post请求传输数据的大小可以自己,也可以无限大

       5. cookie和session的区别

        存放位置不同:cookie存放在客户端,session存放在服务端的

        存取方式不同 : cookie用键值对,session可以保存任何内容

        安全性 : cookie保存在客户端,所以安全性比session低

        有限期不同 : cookie可以设置时间,session则不能

              set-cookie:[expires过期、到期)=new.Date(Date.now() +10 *1000)]   10S后过期,如果不设置默认是关闭浏览器立即失效

        对服务器压力不同 : 处于高并发情况下,cookie比session要高,因为它是保存在客户端的

       6.输入URL后HTTP请求返回完整的过程

        

       7.网络模式

        

       8.三次握手的过程

        

           SYN(synchronous建立联机)    ACK(acknowledgement 确认)    Sequence number(顺序号码)

             第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;
          第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包;
          第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。
        4.四次挥手

         

             FIN  (希望断开连接)    ACK(acknowledgement 确认)    Sequence number(顺序号码)  

        5.三次握手和四次挥手的面试点

         为什么不能用两次握手进行连接    

         三次握手是为了确保双方都已经进入准备好的状态,可以进行通信,而两次握手的创建可能造成死锁 

         假如:当C给S发一个连接请求,然后把C一个应答,这时候S已经认为创建成功了,但是C认为还没有创建成功,将忽略S那边发来的数据,还在等待应答中,S发出的分组超时后,

            再次发送请求,这样就会形成死锁

          如果已经建立了连接,但是客户端突然出现故障了怎么办?

        TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,

        时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,

        服务器就认为客户端出了故障,接着就关闭连接。

       6.TCP和UDP的区别

           a.基于连接与无连接;
              b.对系统资源的要求(TCP较多,UDP少);
              c.UDP程序结构较简单;
              d.流模式与数据报模式 ;

         e.TCP保证数据正确性,UDP容易丢包;TCP保护数据的顺序,UDP不行   UDP应用于IP电话和实时视频会议

      7.Http请求协议的讲解

    1. Accept : 代表接受文本和html格式
      text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    2. Accept-Encoding : 支持什么样子的编码
      gzip, deflate, br
    3. Accept-Language : 中国语言
      zh-CN,zh;q=0.9
    4. Cache-Control : 支持缓存类型
      max-age=0
    5. Connection :  长连接服务
      keep-alive
    6. Cookie :  服务器给客户端标识的认证
      IMCDNS=1
    7. Host :
      www.imooc.com
    8. User-Agent :  请求主机的类型
      Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.35 Safari/537.36

      8.请求头的常见属性详解

       User-Agent : 向服务器请求的操作系统以及版本号等

       Referer :  你当前网页的上一个地址

       Cache-Control :  缓存

       Connection :  连接的类型(长连接)

       Range :  多线程取舍时候,截取某一个字段

       If-Match :  

       If-Modified-Since : 

       If-None-Match : 

      9.响应头的讲解

       Cache-Control : 缓存

       Content-Encoding : gzip  编码格式: 压缩

       Content-Type : text/html  直接的文本、html类型

       响应码 : 100-199     信息提示

           200-299     成功

           300-399     重定向

           400-499     客户端错误

           500-599     服务端错误

      八、自定义注解的学习

        @Retention:注解的保留位置         

        @Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含

        @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时或者反射都无法获得,

        @Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

      

        @Target:注解的作用目标        

        @Target(ElementType.TYPE)   //接口、类、枚举、注解

        @Target(ElementType.FIELD) //字段、枚举的常量

        @Target(ElementType.METHOD) //方法

        @Target(ElementType.PARAMETER) //方法参数

        @Target(ElementType.CONSTRUCTOR)  //构造函数

        @Target(ElementType.LOCAL_VARIABLE)//局部变量

        @Target(ElementType.ANNOTATION_TYPE)//注解

        @Target(ElementType.PACKAGE) ///包   

             @Document:说明该注解将被包含在javadoc中

         @Inherited:说明子类可以继承父类中的该注解

        案例:

        @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
        @Retention(RetentionPolicy.SOURCE)
        public @interface Xml {
          String[] layouts();
        }

        @Xml(layouts = "activity_main")

    ------------------------回家需要再调试看看---------------------------------

      

       

    2.Activity之间的通信
      Intent/Bundle

             

      3.Activity向Fragment传递数据

       1).Bundle之间通信

        fragment.setArguments------>Activity与Fragment之间的通信桥梁

        

             getArguments()---->获得Bundle对象,还是key-value的模式

        

       2).直接在Activity之间定义

        

        

        在onAttach绑定时候,强制转换Acitivity的对象获得真实对象

       4.Fragment向Activity对象传递数据

        调用流程:

        

        

        

        

      5.Activity与Service之间通信

       1).绑定服务,利用ServiceConnection之间的通信

        Activity写的代码:

        

        Service写的代码:

        

       2).利用Intent之间的通信

        

        

       3).定义一个callback接口来监听服务中进程的变化

        Service定义接口

         

        Activity进行数据的调用

        

      7.service和IntentService的区别

       onHandleIntent在IntentService是抽象类,需要继承去实现的

      

       相比与Service它使用好处是不用你去手动释放,当你执行完onHandleIntent就会释放service,

       其次就是他可以通过执行HandlerThread执行异步操作

      8.service的启动和绑定的讲解

        service的绑定:

       

         

      启动服务比绑定服务的优先级高

      先绑定服务后启动服务:  绑定服务会转为启动服务运行状态,如果绑定的activity销毁,服务会继续运行

      先启动服务后绑定服务:  服务不会转为绑定服务状态,会和Activity绑定,但是activity销毁,会按启动服务生命周期走

      startService : 让服务长期运行在后台,但是无法与服务进行通讯

      bindServcie : 可以与服务进行通讯,但是无法长期运行在后台

     9.parcelable和serializable区别学习

      组件之间存储数据一般用parcelable,serializable将对象写到磁盘中

      序列化:  内存中的对象----->磁盘

      反序列化: 磁盘中的对象---->内存

      parcelable的实现步骤:

      1)implements Parcelable

      2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据

      3)重写describeContents方法,内容接口描述,默认返回0就可以

      4)实例化静态内部对象CREATOR实现接口Parcelable.Creator

      public class MyParcelable implements Parcelable
     {
         private int mData;

         public int describeContents()
         {
             return 0;
         }

         public void writeToParcel(Parcel out, int flags)
         {
             out.writeInt(mData);
         }

         public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>()
         {
             public MyParcelable createFromParcel(Parcel in)
             {
                 return new MyParcelable(in);
             }

             public MyParcelable[] newArray(int size)
             {
                 return new MyParcelable[size];
             }
         };
         
         private MyParcelable(Parcel in)
         {
             mData = in.readInt();
         }
     }

      简而言之: 通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象

     10.AIDL的使用

        

     11.WebView面试讲解

       1).webview在布局文件中的使用: webview写在其他容器中时(webview完全销毁的办法,否则会内存泄漏)

       2).webviewClient.onPageFinished-------->WebChromeClent.onProgressChanged() : 页面跳转时候调用这个函数


     

       

       

       

       

             

              

      

    
    
  • 相关阅读:
    Dockerfile基于centos镜像编译安装httpd
    Dockerfile基于centos镜像编译安装nginx
    Dockerfile介绍和常用指令
    Docker存储卷
    正则表达式
    Sed与Awk
    Shell函数
    Shell脚本基础
    Autofs
    Podman
  • 原文地址:https://www.cnblogs.com/liunx1109/p/11524060.html
Copyright © 2020-2023  润新知