Android面试题知识点积累

目录

·  主流网络请求框架库对比

·  SparseArray与HashMap的区别?

·  序列化Serializable和Parcelable的理解和区别

·  Synchronized和lock的区别

· 为什么系统不建议在子线程访问UI?

·  Android性能优化之apk瘦身技巧

·  Service和IntentService的区别

·  屏幕适配

 ·  什么是ANR ? 什么情况会出现ANR ?如何避免 ?

·  多线程是否一定会高效(优缺点) 

·  Android App 启动速度优化 

·Android中多进程方式导致的全局Application的OnCreate多次被调用

·活动(Activity)的四种启动模式

·  主流网络请求框架库对比

网络请求框架库对比图
网络请求框架对比图

·  SparseArray与HashMap的区别?

  • SparseArray适用于key为int的场合,HashMap则使用于各种场合
  • SparseArray的内存占用较HashMap少
  • SparseArray性能和HashMap比并没有优势
  • 当使用HashMap(K, V),如果K为整数类型时,使用SparseArray的效率更高。
  • HashMap 与 SparseArray比较:

  • 当数据量在1000以上,推荐使用HashMap。
  • 当数据量 在500-1000,HashMap 和SparseArray性能差不多。
  • 当数据量 少于500时,使用SparseArray 要优于HashMap。

·  序列化Serializable和Parcelable的理解和区别

转载:序列化Serializable和Parcelable的理解和区别 - 简书

为什么要了解序列化?—— 进行Android开发的时候,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。

序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

实现Parcelable的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

·  Synchronized和lock的区别

转载出处:synchronized 和Lock区别_洞玄之境的博客-CSDN博客_synchronized和lock的区别

区别如下: 

来源: 
lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;

·异常是否释放锁: 
synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。) 

·是否响应中断 
lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断; 

·是否知道获取锁 
Lock可以通过trylock来知道有没有获取锁,而synchronized不能; 

Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

·性能对比

如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度,

1、synchronized和lock的用法区别

synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

lock:一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

· 为什么系统不建议在子线程访问UI?

因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态。

那为什么不对UI控件的访问加上锁机制呢?

缺点有两个:

·首先加上锁机制会让UI访问的逻辑变得复杂。

·其次锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。

·  Android性能优化之apk瘦身技巧

转载出处:Android性能优化之APK瘦身详解(瘦身73%)_aserbao的博客-CSDN博客_android apk瘦身

  • 手动lint检查,手动删除无用资源
  • 尽量减少第三方库的引用
  • 重新编译so文件,用更小的库代替(不熟悉,酌情处理)
  • 将大资源文件放到服务端,启动后自动下载使用。
  • 如果你的dex文件太大,检查是否引入了重复功能的第三方库(图片加载库,glide,picasso,fresco,image_loader,如果不是你一个人单独开发完成的很容易出现这种情况),尽量做到一个功能点一个库解决。
  • 避免使用枚举,优化效果也不会特别明显
  • 使用tinypng等图片压缩工具对图片进行压缩
  • 大部分图片使用Webp格式代替
  • 尽量不要在项目中使用帧动画
  • 使用gradle开启shrinkResources
  •  buildTypes {
            release {
                // 不显示Log
                buildConfigField "boolean", "LOG_DEBUG", "false"
                //混淆
                minifyEnabled true
                // 移除无用的resource文件
                shrinkResources true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.release
            }
        }
    

    ·  Service和IntentService的区别

       链接:https://www.jianshu.com/p/0b4b91e7329d 

Service生命周期图对比

Service

Service 是长期运行在后台的应用程序组件。

Service 不是一个单独的进程,它和应用程序在同一个进程中,Service 也不是一个线程,它和线程没有任何关系,所以它不能直接处理耗时操作。如果直接把耗时操作放在 Service 的 onStartCommand() 中,很容易引起 ANR .如果有耗时操作就必须开启一个单独的线程来处理

IntentService

IntentService 是继承于 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。 那么,用 IntentService 有什么好处呢?首先,我们省去了在 Service 中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止 Service


·  屏幕适配

参考这篇文章:一种非常好用的Android屏幕适配 - 简书

 ·  什么是ANR ? 什么情况会出现ANR ?如何避免 ?

参考回答:

  • ANR(Application Not Responding,应用无响应):当操作在一段时间内系统无法处理时,会在系统层面会弹出ANR对话框
  • 产生ANR可能是因为5s内无响应用户输入事件、10s内未结束BroadcastReceiver、20s内未结束Service
  • 想要避免ANR就不要在主线程做耗时操作,而是通过开子线程,方法比如继承Thread或实现Runnable接口、使用AsyncTask、IntentService、HandlerThread等

·  多线程是否一定会高效(优缺点) 

多线程的优点

  • 方便高效的内存共享 - 多进程下内存共享比较不便,且会抵消掉多进程编程的好处
  • 较轻的上下文切换开销 - 不用切换地址空间,不用更改CR3寄存器,不用清空TLB
  • 线程上的任务执行完后自动销毁

多线程的缺点

  • 开启线程需要占用一定的内存空间(默认情况下,每一个线程都占512KB)
  • 如果开启大量的线程,会占用大量的内存空间,降低程序的性能
  • 线程越多,cpu在调用线程上的开销就越大
  • 程序设计更加复杂,比如线程间的通信、多线程的数据共享

综上得出,多线程不一定能提高效率,在内存空间紧张的情况下反而是一种负担,因此在日常开发中,应尽量

  • 不要频繁创建,销毁线程,使用线程池
  • 减少线程间同步和通信(最为关键)
  • 避免需要频繁共享写的数据
  • 合理安排共享数据结构,避免伪共享(false sharing)
  • 使用非阻塞数据结构/算法
  • 避免可能产生可伸缩性问题的系统调用(比如mmap)
  • 避免产生大量缺页异常,尽量使用Huge Page
  • 可以的话使用用户态轻量级线程代替内核线程

·  Android App 启动速度优化 

冷启动(Cold start)

冷启动是指APP在手机启动后第一次运行,或者APP进程被kill掉后在再次启动。
可见冷启动的必要条件是该APP进程不存在,这就意味着系统需要创建进程,APP需要初始化。在这三种启动方式中,冷启动耗时最长,对于冷启动的优化也是最具挑战的。因此本文重点谈论的是对冷启动相关的优化。

温启动(Warm start)

App进程存在,当时Activity可能因为内存不足被回收。这时候启动App不需要重新创建进程,但是Activity的onCrate还是需要重新执行的。场景类似打开淘宝逛了一圈然后切到微信去聊天去了,过了半小时再次回到淘宝。这时候淘宝的进程存在,但是Activity可能被回收,这时候只需要重新加载Activity即可。

热启动(Hot start)

App进程存在,并且Activity对象仍然存在内存中没有被回收。可以重复避免对象初始化,布局解析绘制。
场景就类似你打开微信聊了一会天这时候出去看了下日历 在打开微信 微信这时候启动就属于热启动。

一旦系统创建应用程序进程,应用程序进程就会负责下一阶段。这些阶段是:
1.创建应用程序对象
2.启动主线程
3.创建主要Activity
4.绘制视图(View)
5.布局屏幕
6.执行初始化绘制

而一旦App进程完成了第一次绘制,系统进程就会用Main Activity替换已经展示的Background Window,此时用户就可以使用App了。

Application OnCrate()优化

1.第三方SDK初始化的处理(懒加载)

Activity onCreate()优化

减少LaunchActivity的View层级,减少View测量绘制时间。
避免主线程做耗时操作

用户体验优化

消除启动时的白屏/黑屏(主题设置)

·Android中多进程方式导致的全局Application的OnCreate多次被调用


原文链接:多进程Application (多次启动的问题)_杨岳龙-CSDN博客_android application 多进程

多进程Application: 有多个进程执行,每个进程的启动,都会调用一次 Application

关于Application 的 onCreate()方法执行多次的问题 
在application 的onCreate()方法中打印log,你会发现,有时会执行多次,这样带来的问题: 
1.浪费资源 
2.对性能造成影响 
3.处理不好可能导致bug

多次调用的原因: Application多进程的问题,应用每启动一个新进程,就会调用一次Application的onCreate()方法。

常见例子: 
1.一些第三方框架可能是一个独立的进程,那么你集成了该框架,就会出现多次调用Application的onCreate()方法的问题。

  override fun onCreate() {
        super.onCreate()

        val processName = getProcessName(this, android.os.Process.myPid());
        Log.e("csj","onCreate$processName")

        if(processName != null){
            val defaultProcess = processName=="包名"
            if(defaultProcess){
                //当前应用的初始化
                //initApp();
            }
        }

    }



fun getProcessName(cxt: Context, pid: Int): String? {
        val am = cxt.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val runningApps = am.runningAppProcesses ?: return null
        for (procInfo in runningApps) {
            if (procInfo.pid == pid) {
                return procInfo.processName
            }
        }
        return null
    }

    解决方案就是在Application的OnCreate的方法里针对不同的进程做不同的初始化即可。 

·活动(Activity)的四种启动模式

         活动(Activity)的四种启动模式

Android 2018 最新面试题(3-5年经验个人面试经历)

参考文章:

https://www.jianshu.com/p/4abe0f9f0cd8

https://www.jianshu.com/p/247e9888bd5f

一种非常好用的Android屏幕适配 - 简书

https://www.jianshu.com/p/0b4b91e7329d 

synchronized 和Lock区别_洞玄之境的博客-CSDN博客_synchronized和lock的区别

序列化Serializable和Parcelable的理解和区别 - 简书

Android App 启动速度优化实现演练 - 简书(启动速度优化)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chen_ShengJie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值