Android 面试笔记总结 2018.09.10-10.01

此篇适合应届毕业生及还没有毕业的学生做的面试准备。
前期知识储备: 当你已经有一点点的Java以及Android基础后(这里是指比如已经掌握《Android的第一行代码》,《Head First Java》等用你自己的方式获取的基础知识),现准备阶段应该读完或正在读《Android 开发艺术探索》和《深入理解Java虚拟机》以及《Java编程思想》,这是我面试时做的准备工作。
前期面试准备

  1. 简历:非常重要。它是让你获得面试机会的第一张牌。
  • 制作简历:这里我的建议可以模仿下载的模板自己制作简历,不仅让你对自己简历的内容更加了解,而且自己进行排版时,就会了解到每个地方写的每个字是否是必要的并且有用的,还会让你的简历不那么千篇一律。
    • 重要信息:姓名、意向、联系电话、邮箱、教育背景及专业、工作经历 > 实习经历 > 校内项目、专业技能、证书、个人网站。
    • 次要信息:性别,年龄,兴趣爱好,自我评价,政治面貌,出生年月,家庭住址。这些我认为是可以省略的,如果自我评价你能写的不那么平凡,请随意选择填写。
    • 项目:是最能展示你基本功的地方,这里,需要注意写清项目的起始日期,而且需要清晰明了,一眼就能看见并看清楚,写清项目的用途及自己负责的内容。最最最重要的地方,你负责的模块,必须保证写的每个字,自己都了解的清清楚楚,明明白白,这样才能体现是你做的,并且面试官才能从你的阐述中,更加深入的了解你做东西的思想及考虑到的地方,也是能够与面试官进一步沟通的一个切入点。别人做的地方,有时间也是可以了解一下,这样才有助于了解整个项目的结构。
    • 篇幅:还没毕业的学生一篇A4纸差不多就能写完,已经毕业的应届生两篇A4纸差不多就能写完。再长就有点过分了。
  • 投递简历:可以在实习僧、拉钩、Boss直聘、58、人才热线上面投递。
    • 投递的时候记得筛选自己喜欢的行业范围,公司规模,公司年限要求等信息,不要自己不喜欢的公司邀请面试就去,去了还浪费时间。
    • 投递成功邀请面试时,首先要看官网,查看该公司的主营产品,也为后期你想面试官提问时有的问,是可以在天眼查,求职网等获取一下简单的公司信息。符合你想要找的公司标准后,再去面试。如果一直没有面试,就要更改简历,这也是一个比较大的问题,还有就是是否是自己筛选的公司要求过高,这也是需要调整的地方。
  1. 面试

    • 自我介绍:说清自己来自哪里,那个学校,什么专业,为什么学这个,未来有什么预期之类的。注意自己开场白的礼貌用语,比如,面试官,您好,下午好,谢谢之类的。自我介绍很多时候是给面试官充分的时间看简历的过程,所以,根本不必太紧张,但你也可以将自我介绍说的更加生动有趣,体现自己的性格特点,这也没什么问题。
    • 沟通: 一定要有自信, 体现在交流时一定要声音正常,不要过于紧张,扭捏,声音小什么的,只要放轻松,正常沟通就好了,不要害怕。不要在面试的时候面试官问的问题都不会,就紧张死了,其实不会是很正常的,不会就直接说不会,千万别装,装活不到两秒,下一个接着的问题就会把你暴露出来。其实面试没什么的,有时候可能刚开始面试,面试官几个问题没打上来,就over了,这也没什么,咱回去查查问的问题,是不是自己水平太低,没达到这个层次,还是面的水平太高,自己要求不够。
    • 多说一嘴:简历投递成功,HR给你面试的机会,就要好好把握,不要心里想着,这公司要求这么高,我去了能行吗?之类的瞎寻思,只要有面试,就多一份机会;既然HR让你过来面试,必然你是符合她当前的用人要求中的某些地方的。
    • 技巧:如果面试的时候刚开始会不知道该如何准备,或者面试官问的有些问题,当时没记住,后期回来想巩固一下,全忘了,这时可以选择在面试的时候进行录音,这也是一个方法吧。回来听录音,不仅能感受到自己面试时候的语气是否正常,表达是否全面,阐述是否清晰,还可以从头捋一遍面试的问题,把不懂不会的全部都查一遍,记一遍,就这样一步一步走,面试也会更加顺利。
  2. 面试内容:2018.09.10-10.1

    1. 有在公司实习吗?做了项目的那些模块?有上线吗?
    2. mvc的理解及使用在activity的架构中的使用
    3. handler机制
    4. service主要是用到的场景
    5. broadcast 的使用场景
    6. 项目中遇到那些问题
    7. listView中的缓存
    8. 图片框架的使用有哪些
    9. 有遇到内存泄漏吗
    10. String可以每次进行拼接吗
    11. 如何将Gson转换成对象
    12. 一个链接如何调起自身的apk
    13. 动画的种类
    14. 自定义view进行解锁样式的绘制
    15. 多线程的几种方式?
    16. 如何将service变成前台进程
    17. 字符串读取使用的输入流
    18. 横竖屏切换时Activity经历的生命周期
    19. 子类是否可以重写父类?
    20. String 和StringBuffer的区别
    21. java中Exception继承自Throwable吗?
    22. Activity的四种状态:Running、Pause、Stop、Destoryed
    23. Activity之间如何传递数据
    24. UDP与TCP的区别
    25. 框架加载图片的过程
    26. 视频播放的生命周期。从播放到回收。
    27. OKHttp的常用接口有哪些。
    28. 自定义view的过程 onMeasure()测量长宽,返回的参数在哪里进行设置?答:设置到setMesureDemissin();
    29. Dagger的用途
    30. Android的文件存储方式有那几种
    31. 有用过RxJava封装一个网络框架吗
    32. 并发的特性
    33. java中将对象置为空,是否可以被垃圾回收机制进行回收
    34. 从一个Activity到另一个Activity,两个actiivty到可见状态都经历了哪些声明周期
    35. java中的GC讲一下
    36. 项目中用到的主流的框架
    37. 使用过的网络框架有哪些,他们之间有什么区别
    38. 介绍一些MVP与MVC
  3. 面试笔记:

    Java

    1. 三大特性

      • 封装: 把客观事物封装成类,将自己的数据和方法只对可信赖的类或对象操作,对不可信的进行隐藏。
      • 继承: 可以使用现有类的所有功能,在无需重新编写原来类的情况下,对功能进行扩展。继承的方式有两种:继承基类、实现接口。
      • 多态: 是指一个类实例的相同方法在不同情形有不同的表现形式。
    2. Exception 与 Error的区别:

      • 联系:
        • 都继承于Throw able,RuntimeException继承自Exception。
        • Exception与Error多是未受检异常。
      • 区别:
        • Error 一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、内存空间不足、方法调用栈溢出,如 StackOverflow、OutofMemoryError
        • Exception表示程序可以处理的异常。
    3. Java 运行时的数据区域分类:

      • 程序计数器:当前线程 所 执行字节码 的 行号指示器。 是线程私有,生命周期与线程相同。
      • Java虚拟机栈Java 方法执行的内存模型 。 每个方法执行的时候,都会创建栈帧(存储 局部变量表、操作栈、动作链接、方法出口等)。每个方法执行对应着一个栈帧虚拟机栈 中从 入栈 到 出栈的过程。是线程私有
      • 本地方法栈:为虚拟机所用到的Native方法服务。是线程私有
      • 方法区被所有线程共享。 包含所有的class 和static 变量,都是整个程序中永远唯一的元素,全局变量、静态变量。
      • Java 堆被所有线程共享。 存储的全部是对象,每个对象包含一个对应的class信息。
    4. Java 垃圾回收机制

      • 当新生代的eden区域存储满的时候进行一个minor GC ,通过然后每次当其满的时候,通常采用(GC Root Tracing) 根搜索算法。(因为引用计数算法不能很好的解决循环引用的问题。)检查存活的对象,将eden和s0中存活的内存放到s1中,清空s0,下次eden满的时候,再将s1中存活的数据和eden中存活的数据放在s0中。反复进行。其中eden和survivor中的内存比例是8:1.
    5. Java 中对象分配的问题

      • 一般通过new 出来的对象通常会分配到堆上。但并不完全是。在栈上还可以有两种分配方式。
        • 栈上分配:如果一个对象的作用域不会逃出方法之外,可以将这个对象分配到栈上,可以随着栈帧出栈而销毁。随着方法的结束而结束,则可以无须通过垃圾回收,减少垃圾收集器的负载。
          • 一是逃逸分析:目的,判断对象的作用于是否有可能逃逸出函数体。
          • 二是标量替换:允许将对象打散分配到栈上。
        • TLAB:(Thread Local Allocation Buffer) 线程本地分配缓冲区。线程专用内存分配区域。TLAB本身占用的是Eden区域,虚拟机为每个线程分配一块TLAB空间。但TLAB能够分配的空间比较小。当一个比当能剩余空间大的对象需要进行存储是,会根据 调整的refill_waste 的最优阈值选择是否 将其存储到栈上 有两种选择,一是重新新建一个TLAB 进行存储,当前的则被浪费掉了,二是将其存储到堆上,当前的TLAB则被保留为下面可能被存储的存储进来。
      • 对象内存分配的两种方法:
        • 指针碰撞:假设Java堆中的内存是绝对规整的,s有一个指针分解点。一边为已被分配的内存,一边为空闲的内存,有对象内存需要分配的时候,则将指针向空闲的那边移动对象大小的距离即可。
        • 空闲列表:如果Java堆中的内存并不规整,已用的和空闲的交错。则虚拟机需要维护一个列表,记录哪些内存块是可用的,在分配表中找出空闲的足够存放需要被存放的空间大小,分配给他。
    6. Object类里面有哪几种方法,作用

      • getClass()、hashCode()、equals()、toString()、clone()、notify()、notifyALL()、wait()
      • 其中,wait是Object类提供的方法,sleep()是Thread类中提供的方法
    7. equals 和 hashCode方法,重写equals的原则()

    8. Volatile 与 Synchronized

      • synchronized关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized,但是要注意volatile关键字是无法替代synchronized关键字的,因为volatile关键字无法保证操作的原子性。通常来说,使用volatile必须具备以下2个条件:

          1. 对变量的写操作不依赖于当前值
        • 2 . 该变量没有包含在具有其他变量的不变式中
        • 总结:保证操作是原子性操作,才能保证使用volatile关键字的程序在并发时能够正确执行
        • volatile 主要是 可见性和禁止指令重排。

        使用场景:

        1.状态标记量

        volatile boolean flag = false;
        while(!flag){
            doSomething();
        }
        public void setFlag(){
            flag = true;
        }
        

        2.double check

        public class Singleton {
            private static volatile Singleton instance;
            private Singleton(){}
            public static Singleton getInstance(){
                if(instance == null){
                    synchronized(Singleton.class){
                        if(instance == null){
                            instance = new Singleton();
                        }
                    }
                }
             return instance;}
        }
        
    9. ListView所用到的设计模式

      • 适配器模式
      • 观察者模式
      • 享元模式
    10. 线程池的种类:

      • newCachedThreadPool: 适用于:执行很多短周期的小程序或者负载较轻的服务器
      • newFixedThreadPool适用于:执行长期的任务,性能好很多
      • newSingleThreadPool适用于:一个任务一个任务执行的场景
      • newScheduledThreadPool适用于:周期性执行的场景
    11. 如何避免内存溢出

      1. 尽早释放无用的对象
      2. 程序进行字符串处理时,减少使用String,多使用StringBuffer
      3. 尽量少用静态变量,因为静态变量是全局的,GC不会回收
      4. 避免集中创建对象,尤其是大对象,如果可以的话,尽量使用流操作
      5. 尽量运用对象池技术以提高系统性能。
        • 生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。
      6. 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。
        • 可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃。
      7. 优化配置。
    12. java线程中的run和start的区别

      • start() 可以启动一个新线程,run()不能
      • start()不能被重复调用,run()可以
      • start()中的run代码可以不执行完就继续执行下面的代码,即进行了线程切换。直接调用run方法必须等待其代码全部执行完才能继续执行下面的代码。
      • start() 实现了多线程,run()没有实现多线程。
    13. 对Object对象二分法排序功能的实现接口

      • 使用Comprable接口的CompareTo(Object o)方法。
    14. 并发所具备的特性:

      • 原子性
      • 有序性
      • 可见性

    Android

    1. Activity之间传输数据的几种方式

      • Intent传递数据
      • ContentProvider 数据库传输传递数据
      • BroadcastReceiver广播接收器传输
      • 采用持久化技术
        • 文件传输
        • SharedPreferences (存储用户名、密码)
        • SQLite数据库
      • service传递传递数据
    2. startActivityForResult 与 onActivityResult 的区别?

      @Override
          public void startActivityForResult(Intent intent, int requestCode) {
              super.startActivityForResult(intent, requestCode);
          }
      
          @Override
          protected void onActivityResult(int requestCode, int resultCode, Intent data) {
              super.onActivityResult(requestCode, resultCode, data);
          }
      
      
      • 通常使用startActivityForResult去启动另一个Activity,用onActivityResult处理从另一个Activity传回的数据。
    3. activity中启动模式及应用场景

      • standard

      • singleTop

        • 用于接收新闻通知等。反复有消息过来,就不需要每次都创建新的activity,直接复用栈顶的activity就好,如果再创建多个相同的新的activity返回时,返回的界面为相同的界面,会显得很奇怪。
        • 用于耗时操作进行返回的时候: 从activity A启动了个service进行耗时操作,或者某种监听,这个时候你home键了,service收集到信息,要返回activityA了,就用singleTop启动,实际不会创建新的activityA,只是resume了。不过使用standard又会创造2个A的实例。
      • singleTask

        • 适合主界面中,用于其他应用调起该界面的时候。适合作为程序的入口,应用于别的程序直接进来,让她浏览程序的主界面就好,不需存在其他的Activity,清空上面的启动就好。
        • 场景:做浏览器、微博之类的应用,比如其他App需要打开我们的浏览器页面,就可以配置他为singleTask模式,保证他只有一个唯一实例,节约内存同时按下返回键后的感官也更顺畅。但是需要注意,提供给人调用的页面最好是栈底元素。因为,如果自己的客户端处于运行状态,按下Home键后台挂起。此时如果使用如果其他应用(比如说QQ)调起自己的客户端某个页面,不做任何处理的情况下,按下回退或者当前 Activity.finish(),页面都会停留在自己的客户端(因为自己的Application回 退栈不为空),这明显不符合逻辑的。
        • 解释:设置被调起的应用称之为B。当自己已经启动B应用的其他界面,按home键,B应用在后台挂起。通过另一个应用调起B应用的欢迎界面,然后按back,会弹出刚刚浏览停留在home是的B的另一个界面,这样就比较奇怪。所以,在调起B的欢迎界面的时候,就将B应用的其他界面全部清空,避免这种奇怪的现象发生。
      • singleInstance

        • 适用需要与程序分离的界面,例如闹钟提醒,可以与设置闹钟分离。互不影响的界面应用。例如(但)但不能用于中间界面,因为放在不同的栈内。

        • 解释:单一实例模式,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。
          可以得出以下结论:

          1. 以singleInstance模式启动的Activity具有全局唯一性,即整个系统中只会存在一个这样的实例。
          2. 以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
          3. 以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中。
          4. 被singleInstance模式的Activity开启的其他activity,能够在新的任务中启动,但不一定开启新的任务,也可能在已有的一个任务中开启。

          换句话说,其实SingleInstance就是我们刚才分析的SingleTask中,分享Activity为栈底元素的情况。

      1. Okhttp请求网络与Volley的网络请求

        OkHttp

      • 物理质量

        使用OkHttp需要 okio.jar (80k), okhttp.jar(330k)这2个jar包,总大小差不多400k,加上自己的封装,差不多得410k。

      • 功能介绍

        Square 公司开源的 OkHttp 是一个专注于连接效率的 HTTP 客户端。OkHttp 提供了对 HTTP/2 和 SPDY 的支持,并提供了连接池,GZIP 压缩和 HTTP 响应缓存功能。

      • 优点

        • 支持http请求,https请求。
        • 支持文件下载。
        • 使用的是HttpURLConnection,不要担心android版本的变换。(至少目前是都支持的)。
        • 支持get,post请求。
        • 基于Http的文件上传。
        • 加载图片。
      • okhttp的使用

        String url = "http://wwww.baidu.com";
        OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求,可以不写
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure: ");
            }
        
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d(TAG, "onResponse: " + response.body().string());
            }
        });
        

      Volley

    • 缺点:
      • 使用的是httpclient、HttpURLConnection
      • 6.0不支持httpclient了,如果想支持得添加org.apache.http.legacy.jar
      • 对大文件下载 Volley的表现非常糟糕
      • 只支持http请求
      • 图片加载性能一般
    • Volley的优点:
      • Volley适用于数据量不大,但通信频繁的网络操作
      • 可以直接在主线程中调用服务端并处理返回结果
      • 可以取消请求,容易扩展,面向接口编程
      • 网络请求线程NetworkDispatcher默认开启了4个,可以优化,通过手机CPU数量
      • 支持重试和优先级设置
      • 默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现
    • 比较:
      • volley需要的空间较小140k,okHttp占用的空间较大410k
    • 音视频通信使用的是Okhttp进行网络下载的。
    1. Retrofit的使用:

      /**
      * 描述:第一步:定义一个接口配置网络请求
      */
      public interface WeatherService {
      //  网络接口的使用为查询天气的接口
      //  
         @GET("weather_mini")
      //  此处回调返回的可为任意类型Call<T>,再也不用自己去解析json数据啦!!!
         Call<WeatherEntity> getMessage(@Query("city") String city);
      
      /**
          * 单纯使用Retrofit的联网请求
          */
         private void doRequestByRetrofit() {
             Retrofit retrofit = new Retrofit.Builder()
                     .baseUrl(API.BASE_URL)//基础URL 建议以 / 结尾
                     .addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器
                     .build();
             WeatherService weatherService = retrofit.create(WeatherService .class);
             Call<WeatherEntity> call = weatherService.getMessage("北京");
             call.enqueue(new Callback<WeatherEntity>() {
                 @Override
                 public void onResponse(Call<WeatherEntity> call, Response<WeatherEntity> response) {
                     //测试数据返回
                     WeatherEntity weatherEntity = response.body();
                     Log.e("TAG", "response == " +  weatherEntity.getData().getGanmao());
                 }
      
                 @Override
                 public void onFailure(Call<WeatherEntity> call, Throwable t) {
                     Log.e("TAG", "Throwable : " + t);
                 }
             });
         }
      

      rxJava+Retrofit的使用

      public interface RxWeatherService {
         @GET("weather_mini")
         Observable<WeatherEntity> getMessage(@Query("city") String city);
      }
      
      private void doRequestByRxRetrofit() {
              Retrofit retrofit = new Retrofit.Builder()
                      .baseUrl(API.BASE_URL)//基础URL 建议以 / 结尾
                      .addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器
                      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//RxJava 适配器
                      .build();
              RxWeatherService rxjavaService = retrofit.create(RxWeatherService .class);
              rxjavaService .getMessage("北京")
                      .subscribeOn(Schedulers.io())//IO线程加载数据
                      .observeOn(AndroidSchedulers.mainThread())//主线程显示数据
                      .subscribe(new Subscriber<WeatherEntity>() {
                          @Override
                          public void onCompleted() {
      
                          }
      
                          @Override
                          public void onError(Throwable e) {
      
                          }
      
                          @Override
                          public void onNext(WeatherEntity weatherEntity) {
                      Log.e("TAG", "response == " + weatherEntity.getData().getGanmao());
                          }
                      });
          }
      
      
      
    2. Android从桌面点击应用程序到启动该应用的过程。

    在这里插入图片描述

    1. RecyclerView 和ListView的区别
    • 缓存区别:如果没有大量的动画效果、不需要频繁更新,RecyclerView与ListView的区别并没有很明显。
    • RecyclerView需要四级缓存,ListView需要两级缓存。
    • RecyclerView的缓存机制确实更加完善,RecyclerView更大的亮点在于提供了局部刷新的接口,通过局部刷新,就能避免调用许多无用的bindView。
    1. Android 的事件分发机制:
    • dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止传递了.
    • dispatchTouchEvent 和 onTouchEvent方法在return false的时候事件都回传给父控件的onTouchEvent处理。
    • onInterceptTouchEvent方法中 return true就会交给自己的onTouchEvent的处理,如果不拦截就是继续往子控件往下传

    在这里插入图片描述

    1. 一个Activity启动后,按返回键,在后台挂起所经历的生命周期以及最后所处的生命周期,再次返回这个Activity所处的状态?
    • 该Activity启动经历的生命周期:onCreate — onStart – onResume
    • 转到后台:onPause ----- onStop
    • 返回可见的前台:onRestart – onStart – onResume
    • 启动 B Activity时此Activity经历:onPause
    • B Activity :onCreate — onstart – onResume
    • 此Activity继续经历:onStop
    • 经验证: onPause onStop onDestory经常在一起。onRestart onStart onResume 经常在一起。最后的状态经常会停留在onResume onPause onStop中
    1. 几种常见的框架的简介:
    • Rxjava: 全局的观察者模式,主要用于简洁的处理异步操作。

      • 优点:随着程序逻辑变得越来越复杂,它依然能够保持简洁。
    • EventBus

      • Retrofit :网络加载框架。Okhttp的加强版,Retrofit + RxJava.
    • Dagger2:依赖注入。从此没有了new 对象。详解:https://www.jianshu.com/p/91c2bb8e6369。

      ​ 便于完成运行时绑定。我们在使用的时候,只需关注该功能如何实现,不会太注重该对象是什么

      ​ 时候new的,以及该对象的生命周期又是如何等。Dagger适合于大型的项目,不适合比较小的项

      ​ 目。

    1. Activity的四种状态:
    • 活动状态:Running
      • 活动状态一般是指该Activity正处于屏幕最显著的位置上显示,即该Activity是在Android活动栈的最顶端。
        一般地当Activity 创建后就是处于该状态中。
        期间触发的函数及顺序为: onCreate() ->onStart() -> onResume()。
      • onStart()是当Activity正在变为可见状态时才会被调用。一般地在此期间可以注册一个广播等等。
        onResume()是在该Activity将要和用户进行交互时被调用,此时Activity位于的活动栈顶部。
    • 暂停状态:paused
      • 暂停状态一般指该Activity已失去了焦点但仍然是可见的状态(包括部分可见)。一个处于暂停状态的Activity只有在系统极度缺乏内存资源的情况下才会被系统强制结束。
        运行状态到暂停状态所触发的函数及顺序为:onResume() -> onPuased()。
        暂停状态恢复至运行状态所触发的函数及顺序为:onPuased() -> onResume()。
      • onPuased()是当一个Activity失去系统焦点后将会被调用,包括见面被部分遮挡,以及设备转入休眠状态等等。一般地在此期间对一些未保存的数据进行持久化并停止其他需要耗费CPU的操作,同时不可进行耗时操作,否则会阻塞系统UI线程。
    • 停止状态:stopped
      • 停止状态一般指该Activity被另一个Activity完全覆盖的状态,这是它仍然保持所有的状态,但是由于该Activity变得不可见,所以系统经常会由于内存不足而将该Activity强行结束。
        暂停状态到停止状态所触发的函数及顺序为:onPuased() -> onStop()。
        停止状态恢复至运行状态所触发的函数及顺序为:onStop() -> onRestart() -> onStart() -> onResume()。
    • 死亡状态:destory
      • 死亡态是指该Activity被系统销毁。当一个Activity处于暂停状态或停止状态时就随处可能进入死亡状态,因为系统可能因内存不足而强行结束该Activity。
        停止状态到死亡状态分为两种情况:(1)由用户操作导致,则执行:onStop() -> onDestroy()。(2)由系统自动强制执行,则该Activity被强行结束。
      • onDestroy()是当一个Activity正在被系统finished期间被调用的。
    1. Activity从横屏切换到竖屏是经历的生命周期:
    • onPause ---- onStop ---- onDestory --onCreate --onStart ---- onResume
    1. 如何将后台的service调到前台
    @Override
        public IBinder onBind(Intent intent) {
    
            //设置为前台服务
            Notification.Builder builder = new Notification.Builder(this);
            builder
                .setContentTitle("播放音乐中..")
                .setContentText("Diamonds")
       			.setWhen(System.currentTimeMillis())
                .setLargeIcon(BitmapFactory
                .decodeResource(getResources(), R.mipmap.ic_launcher));
            Notification notifation = builder.getNotification();
           //重点:
            startForeground(2, notifation);
    
            return mBinder;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mediaPlayer != null)
                mediaPlayer.release();
            //重点:
            stopForeground(true);
        }
    
    • onBind/onStartCommand中调用startForeground(),在onDestory调用stopForegroun()方法.
    1. ListView的优化:
    • 复用convertView;
    • 缓存item条目的引用–viewHolder
    • 数据优化
      • 进行分批处理—优化了用户体验
        进行分页处理—优化了内存空间
      • 设置ListView的滚动监听器:setOnScrollListener(new OnScrollListener{….})
      • 分批加载数据,只关心静止状态:关心最后一个可见的条目,如果最后一个可见条目就是数据适配器(集合)里的最后一个,此时可加载更多的数据。在每次加载的时候,计算出滚动的数量,当滚动的数量大于等于总数量的时候,可以提示用户无更多数据了。
    1. res/raw和asserts的相同点:
    • 相同点:两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制文件
    • 不同点:res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID,即R.id.filename,assets文件夹下的文件不会被映射到到R.java文件中,访问的时候需要AssetManager类
    • .res/raw不可以有目录,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹
    1. MVP的设计模式

      • 用途:解耦。
      • 详解:https://www.jianshu.com/p/91c2bb8e6369。
      • view只负责加载内容显示,给我什么内容我就加载什么内容,不用考虑数据是从哪里来的。
      • Model负责处理数据,更改数据的方式,从本地获取还是从网络获取等
      • presenter只需负责从model中拿取数据,不关心数据怎么来的,然后将数据给view接口,不用关心view要将他如何进行显示。
    2. 自定义View

      • 详解:https://www.cnblogs.com/CVstyle/p/6399188.html
      • 步骤:测量、布局和绘制三个步骤 onMesure()、onLayout()、onDraw()
          1. 自定义View的属性;
          2. 在View的构造方法中获得自定义的属性;
          3. 重写onMeasure(); --> 并不是必须的,大部分的时候还需要覆写
          4. 重写onDraw();
          1. 当控件的父元素正要放置该控件时调用View的onMeasure()。
          2. ViewGroup会问子控件View一个问题:“你想要用多大地方啊?”,
          3. 然后传入两个参数——widthMeasureSpec和heightMeasureSpec;
          4. 传递子控件View的高度和宽度到setMeasuredDimension()里,直接告诉父控件需要多大地方放置子控件。在onMeasure()的最后都会调用setMeasuredDimension()
          5. 系统帮我们测量的高度和宽度都是MATCH_PARENT;当我们设置明确的宽度和高度时,系统测量的结果就是我们设置的结果。
            1. 重写之前先了解MeasureSpec的specMode,一共三种类型:
              • EXACTLY:一般是设置为明确的值或者是精确的值,Parent为子View决定了一个绝对尺寸,子View会被赋予这个边界限制,不管子View自己想要多大;
              • AT_MOST:表示子布局限制在一个最大值内,代表最大可获取的空间;代表子View可以是任意的大小,但是有一个绝对尺寸上限;
              • UNSPECIFIED:表示子布局想要多大就多大,很少使用;代表Parent没有对子View强加任何限制,子View可以是它想要的任何尺寸;
      • viewGruop是view的子类,是所有布局的父类。
    3. Android的文件存储方式有哪几种?

      • Android中有5种数据存储方式,分别为文件存储SQLite数据库SharedPreferencesContentProvider网络

      • 每种存储方式的特点如下:

        • 文件存储

        文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供openFileInput()和openFileOutput()方法来读取设备上的文件。

        • SQLite数据库

        SQLite是Android所集成的一个轻量级的嵌入式数据库,它不仅可以使用Andorid API操作,同时它也支持SQL语句进行增删改查等操作。

        • SharedPreferences

        SharedPreferences是Android提供的用于存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。不仅可以在同一个包下使用,还可以访问其他应用程序的数据,但是由于SharedPreferences的局限性,在实际操作中很少用来读取其他应用程序的数据。

        • ContentProvider

        ContentProvider主要用于不同应用程序之间共享数据,ContentProvider更好的提供了数据共享接口的统一性,使不同应用共享数据更规范和安全。

        • 网络存储数据

        通过网络上提供的存储空间来上传(存储)或下载(获取)我们存储在网络空间中的数据信息

    4. 进程间通信的几种方式

      • Bundle
      • 文件共享
      • Messenger
      • AIDL
      • ContentProvider
      • Socket
    5. Android性能优化

      • 布局优化:尽量减少布局文件的层级,可以使用等标签进行重用布局。
      • 绘制优化:避免在onDraw()中使用大量计算和频繁绘制,最好保持每次绘制时间不超过16ms.
        并且不要在onDraw()中创建局部对象,因为它可能会被频繁调用,造成一瞬间 产生大量的临时对象需要被回收。
      • 内存泄漏优化
        • 禁止在Activity中使用静态变量引用this,会导致该Activity无法进行回收。
        • 动画的内存优化,在onDestory()中要调用animator.cancel()来进行停止动画,不然一直会在后台运行。
        • 避免创建过多的对象
        • 不过多的使用枚举类型
        • 常量使用static final修饰
        • 适当的使用弱引用和软引用
        • 采用内存缓存和磁盘缓存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值