Android面试题收集

来源:互联网 发布:淘宝产品历史价格 编辑:程序博客网 时间:2024/05/22 07:56

总结下最近面试被问到比较频繁的技术问题。当然,网上已经有相当多优秀的文章对相应问题做出了解答,因此我不会重复造轮子。

基础

自定义View中,View的绘制流程

推荐看自定义View系列教程,一切自定义View相关的问题几乎都可以找到答案,已工作的也可以查漏补缺。


自定义View如何考虑机型适配

被问到这个问题愣了一下,因为没遇到过自定义View的机型适配问题,大概是功力不够吧。我的回答是:

  • 慎用硬件加速。硬件加速不但不适用于某些绘制操作(详见Hardware Acceleration-Unsupported Drawing Operations),某些手机也会出现适配问题。
  • 在屏幕适配上,根据需求有时要权重适配。由于View的三个回调中都是基于px计算,需要获取设备宽高自行计算View的适当大小。
  • 设计上遵循MD,无论对版本适配还是用户体验都是有利的。

说一说ART

在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。这样的话,应用的首次启动和执行都会变得更加快速。
对于开发者而言,ART有如下重要特性:

  • AOT加速应用首次启动时间,当然安装速度会比Dalvik稍慢,应用机器码占用存储空间也更大。
  • 更优秀的GC性能。
  • 更完善的异常报告。

更多参考ART and Dalvik。


项目经验

如何处理APP崩溃

这里见仁见智。我的想法首先设置异常处理:

//捕捉异常,在友盟之前设置不会覆盖友盟if(!PackageUtils.isDebugMode(context)) Thread.setDefaultUncaughtExceptionHandler(this);

然后上报异常,重启应用:

  @Override  public void uncaughtException(Thread thread, Throwable ex) {      if (ex != null) {          Logger.e(ex.getMessage());      }      if (PackageUtils.isDebugMode(context)) {          //不作处理      } else {          //如果没有集成第三方异常上报,在这里上报异常          //...          //结束进程,重新打开APP          Intent intent = getBaseContext().getPackageManager()              .getLaunchIntentForPackage(getBaseContext().getPackageName());          PendingIntent restartIntent = PendingIntent.getActivity(              getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT          );          AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);          mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);          android.os.Process.killProcess(android.os.Process.myPid());      }  }

还有一个项目Cockroach思路很棒,其原理是通过handler post一个死循环,而这个循环中调用Looper.loop(),ActivityThread中的死循环就被架空了,核心代码:

new Handler(Looper.getMainLooper()).post(new Runnable() {            @Override            public void run() {               //主线程异常拦截                while (true) {                    try {                        Looper.loop();//主线程的异常会从这里抛出                    } catch (Throwable e) {                    }                }            }        });        sUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();         //所有线程异常拦截,由于主线程的异常都被我们catch住了,所以下面的代码拦截到的都是子线程的异常        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {            @Override            public void uncaughtException(Thread t, Throwable e) {            }        }});

性能优化

这个问题可能需要许多篇文章才能讲个……入门。不过常用的也不多:

  • 使用Android Monitors,主要观察Memory一栏是否有内存抖动,进而分析内存泄露的代码位置。深入的内存分析可能要用到MAT。
  • 使用TraceView分析耗时方法。这个常用于冷启动时间优化。
  • 使用Android Lint检查无用资源文件、不规范代码等问题,防患于未然。
  • 开启StrictMode分析潜在问题。
  • 布局优化,通常需要避免复杂嵌套布局,嵌套weight,过度重复绘制(可以在开发者选项中开启“显示GPU过度绘制”来检测)。

推荐这篇合集Android性能优化的方方面面。


适配

嗯,面试中的永恒话题。

  • 屏幕适配
  • 权限适配,这个问题可以深入展开,比如做过悬浮窗权限适配的苦逼一定对这篇文章感同身受。
  • .so库适配
  • 版本适配,自从5.0起就比较坑爹了,6.0和7.0可以看看这篇鹅厂专家详解Android N适配要点。

本地密钥安全

Best Practices for Security


平时如何使用Gradle,以及Gradle的原理(构建流程)

官网的两篇文章相当不错:
Gradle Build
Gradle Tips and Recipes
如果需要稍微深入的了解,可以看看:
Understanding Android Gradle build files
如果再吐吐苦水说说Gradle的坑点,此时装逼效果满分(还容易引起共鸣)。


0 0
原创粉丝点击