Android面试——2019面试心得(已获得offer)

最近出去找工作了,分享一下我在面试过程中遇到的问题,希望对Android找工作的小伙伴有帮助。

1.谈谈Android事件分发。

Android事件分发顺序是Activity->ViewGroup->View,都是在dispatchTouchEvent()方法开始调用。

2.如何设计一个图片加载库,讲一下思路

选用Glide图片加载库,使用单例模式,让应用层那边可以链式调用图片加载库,使用Glide内部加载动画,设置图片是是否加载成功的回调。

3.在okHttp基础上设计一个网络请求组件,讲一下思路

使用okhttp实现get、post、文件上传和下载请求、每种请求分两种情况自定义请求的情况和没有自定义请求头的情况。响应类型分为Json和文件类型响应处理,做出统一的错误处理将相关的状态回调给调用网络请求的地方,封装一个基于okhttpClient的网络请求类将网络请求和网络请求响应类关联起来,这样就完成一个okhttp的网络请求类。

4.你了解到的多渠道打包方式有哪几种
  • 原始多渠道打包
    • 直接在清单文件中定义meta标签设置渠道值,读取对应值当做渠道id;
    • 或者直接将渠道写入java代码中;
    • 优缺点:操作简单,但是当渠道数量过多时消耗时间过长,需要多次修改id值。
  • 友盟多渠道打包
    • 原理:清单文件添加渠道标签读取对应值;
    • 打包后修改渠道值的两种方法;
    • 第一种方法:通过ApkTool进行解包,然后修改AndroidManifest中修改渠道标示,最后再通过ApkTool进行打包、签名。
    • 第二种方法:使用AXML解析器axmleditor.jar,拥有很弱的编辑功能,工程中用来编辑二进制格式的 AndroidManifest.xml 文件。
  • 美团多渠道打包
    • 直接将apk文件解压缩,然后在META-INF中间中添加以渠道名命名的空文件;
    • 代码中读取该文件名作为渠道名;
    • 该种方式不需要重新对apk进行签名,操作简单,也可将添加渠道文件的步骤做成Python脚本。实现自动化添加;
    • 优缺点:需要将apk解压缩,如果APK包较大则解压缩所需时间较长。
  • 360多渠道打包
    • 利用的是Zip文件“可以添加comment(摘要)”的数据结构特点,在文件的末尾写入任意数据,而不用重新解压zip文件;
    • apk文件就是zip文件格式;
    • 不需要对apk文件解压缩和重新签名即可完成多渠道自动打包,高效速度快,无兼容性问题。
5.简单讲述一下rxJava的原理

rxJava是异步线程库,使用观察者模式实现的,主要是有Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。订阅subscribe你关心的Observerable对象,你可以对这些对象进行操作和全程监控。

6.Gilde的图片为什么能Activity的生命周期绑定到一起?

Gilde是根据with方法传入的上下文使用RequestManager请求绑定Activity生命周期,RequestManager类实现LifecycleListener生命周期监听器类,利用一个空白的Fragment获取生命周期同步达到绑定的当前界面的效果。

7.Android实现下载功能(断点续传)、怎么实现进度条更新?

使用Service,利用广播通知Activity更新界面、DownloadTask下载的异步类,在下载的过程中,利用广播通知Activity修改进度条更新。

8.ANR是什么?怎么去避免?

ANR全名Application Not Responding, 也就是"应用无响应".
①不要在主线程中做耗时的操作,而应放在子线程中来实现。如onCreate()和onResume()里尽可能少的去做创建操作。
②应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
③避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
④service是运行在主线程的,所以在service中做耗时操作,必须要放在子线程中。

9.App的优化有哪些?

①App启动优化,Application的onCreate(特别是第三方SDK初始化),首屏Activity的渲染都不要进行耗时操作,如果有,就可以放到子线程或者IntentService中。
②布局优化,尽量不要过于复杂的嵌套,可以使用<include><merge><ViewStub>标签。
③响应优化,过于复杂的布局,UI不要做复杂的运算。
④内存优化,减少图片的大小,对图片先进行压缩处理。
⑤电池使用优化,优化网络请求,关闭使用的定位GPS功能。
⑥网络优化,适当的使用网络缓存,避免不要的流量和重复加载。

10.什么情况下会引起内存泄漏?

内存泄漏是对象没有办法被回收。内存泄漏的原因可能是:

  1. Handler 引起的内存泄漏,解决办法:将Handler声明为静态内部类,就不会持有外部类SecondActivity的引用,其生命周期就和外部类无关,如果Handler里面需要context的话,可以通过弱引用方式引用外部类。
  2. 单例模式引起的内存泄漏,解决办法:Context是ApplicationContext,由于ApplicationContext的生命周期是和app一致的,不会导致内存泄漏。
  3. 非静态内部类创建静态实例引起的内存泄漏,解决办法:把内部类修改为静态的就可以避免内存泄漏了。
  4. 非静态匿名内部类引起的内存泄漏,解决办法:将匿名内部类设置为静态的。
  5. 注册/反注册未成对使用引起的内存泄漏,解决办法:注册广播接受器、EventBus等,记得解绑。
  6. 资源对象没有关闭引起的内存泄漏,解决办法:在这些资源不使用的时候,记得调用相应的类似close()、destroy()、recycler()、release()等方法释放。
  7. 集合对象没有及时清理引起的内存泄漏,解决办法:通常会把一些对象装入到集合中,当不使用的时候一定要记得及时清理集合,让相关对象不再被引用。
11.内存溢出是什么?

内存溢出称为OOM,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存溢出通俗的讲就是内存不够用。

12.介绍一下图片的三级缓存。

①内存缓存,读取速度最快。
②硬盘缓存(文件缓存),读取速度比内存缓存稍慢。
③网络缓存,读取速度最慢。

13.谈谈你对Handle的理解。

Handler是实现线程之间的通信,在整个流程中主要有四个对象分别是Handler,Message,MessageQueue,Looper。当应用创建的时候,就会在主线程中创建handler对象,
我们通过要传送的消息保存到Message中,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop()方法,不断的从MessageQueue中取出Message交给handler进行处理。从而实现线程之间的通信。

14.讲一下你理解的JAVA GC原理

GC是垃圾收集算法,核心思想是对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象。如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能。

15.HTTP链接的特点

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”或者“短链接”。

16.TCP和UDP的区别

TCP是面向连接的,由于tcp连接需要三次握手,所以能够最低限度的降低风险,保证连接的可靠性。
UDP不是面向连接的,udp建立连接前不需要与对象建立连接,无论是发送还是接收,都没有发送确认信号。所以说udp是不可靠的。

17.你了解过Kotlin协程吗?

协程是比线程更加轻量的线程,或者称为微线程。使用协程的好处是:当它挂起的时候,它不会阻塞其他线程。协程底层库也是异步处理阻塞任务,但是这些复杂的操作被底层库封装起来,协程代码的程序流是顺序的,不再需要一堆的回调函数,就像同步代码一样,也便于理解、调试和开发。它是可控的,线程的执行和结束是由操作系统调度的,而协程可以手动控制它的执行和结束。

18.手写冒泡算法
public void bubblingSort(Integer[] arr, int n) {
        if (n <= 1) {
       	 	//如果只有一个元素就不用排序了
			return; 
		}      

        for (int i = 0; i < n; ++i) {
            // 提前退出冒泡循环的标志位,即一次比较中没有交换任何元素,这个数组就已经是有序的了
            boolean flag = false;
            // 遍历数组里面的数据
            for (int j = 0; j < n - i - 1; ++j) {      
                if (arr[j] > arr[j + 1]) {        
                	// 设置这两个相邻的数是逆序的,交换
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = true;
                }
            }
            if (!flag){
           		 //没有数据交换,数组已经有序,退出排序
				break;
			} 
        }
    }

以上就是我出去面试遇到的面试题,希望对小伙伴们有帮助。我已经成功获得offer,投入新工作当中。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值