前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android需要收藏的面试题合集

Android需要收藏的面试题合集

作者头像
陈宇明
发布2020-12-16 10:43:52
4060
发布2020-12-16 10:43:52
举报
文章被收录于专栏:设计模式
码仔,今天就给大家带来了《每日一道面试题》的第十二期:

01

ListView如何提高效率

1、使用分页加载,不要一次性加载所有数据。

2、复用convertView。在getItemView中,判断converView是否为空,如果不为空,可复用。

3、异步加载图片。Item中如果包含有webimage,那么最好异步加载。

4、快速滑动时,不显示图片。当快速滑动列表(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来

02

谈谈Android的安全机制

  1. Android 是基于Linux内核的,因此 Linux 对文件权限的控制同样适用于 Android。在 Android 中每个应用都有自己的/data/data/包名 文件夹,该文件夹只能该应用访问,而其他应用则无权访问。
  2. Android 的权限机制保护了用户的合法权益。如果我们的代码想拨打电话、发送短信、访问通信录、定位、访问、sdcard 等所有可能侵犯用于权益的行为都是必须要在 AndroidManifest.xml 中进行声明的,这样就给了用户一个知情权。
  3. Android 的代码混淆保护了开发者的劳动成果。

03

LruCache算法源码解析

我们先看下LruCache算法的构造方法。

代码语言:javascript
复制
public LruCache(int maxSize) {
     if (maxSize <= 0) {
         throw new IllegalArgumentException("maxSize <= 0");
     }
     this.maxSize = maxSize;
     this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
 }

从构造方法的源码我们可以看到,在这段代码中我们主要做了两件事。第一是判断下传递来的最大分配内存大小是否小于零,如果小于零则抛出异常,因为我们如果传入一个小于零的内存大小就没有意义了。之后在构造方法内存就new了一个LinkHashMap集合,从而得知LruCache内部实现原理果然是基于LinkHashMap来实现的。

之后我们再来看下存储缓存的put()方法。

代码语言:javascript
复制
public final V put(K key, V value) {
  if (key == null || value == null) {
     throw new NullPointerException("key == null || value == null");
  }
 
  V previous;
     synchronized (this) {
     putCount++;
     size += safeSizeOf(key, value);
     previous = map.put(key, value);
  if (previous != null) {
     size -= safeSizeOf(key, previous);
  }
 }
 
   if (previous != null) {
     entryRemoved(false, key, previous, value);
  }
 
  trimToSize(maxSize);
   return previous;
 }

从代码中我们可以看到,这个put方法内部其实没有做什么很特别的操作,就是对数据进行了一次插入操作。但是我们注意到最后的倒数第三行有一个trimToSize()方法,那么这个方法是做什么用的呐?我们点进去看下。

代码语言:javascript
复制
public void trimToSize(int maxSize) {
   while (true) {
    K key;
    V value;
   synchronized (this) {
    if (size < 0 || (map.isEmpty() && size != 0)) {
     throw new IllegalStateException(getClass().getName()
     + ".sizeOf() is reporting inconsistent results!");
 }
 
 if (size <= maxSize) {
     break;
 }
 
 Map.Entry<K, V> toEvict = map.eldest();
     if (toEvict == null) {
         break;
     }
 
     key = toEvict.getKey();
     value = toEvict.getValue();
     map.remove(key);
     size -= safeSizeOf(key, value);
     evictionCount++;
   }
 
     entryRemoved(true, key, value, null);
   }
 }

我们可以看到,这个方法原来就是对内存做了一次判断,如果发现内存已经满了,那么就调用map.eldest()方法获取到最后的数据,之后调用map.remove(key)方法,将这个最近最少使用的数据给剔除掉,从而达到我们内存不炸掉的目的。

我们再来看看get()方法。

代码语言:javascript
复制
public final V get(K key) {
     //key为空抛出异常
     if (key == null) {
        throw new NullPointerException("key == null");
    }
 
     V mapValue;
     synchronized (this) {
     //获取对应的缓存对象
     //get()方法会实现将访问的元素更新到队列头部的功能
         mapValue = map.get(key);
     if (mapValue != null) {
         hitCount++;
     return mapValue;
  }
     missCount++;
 }

get方法看起来就是很常规的操作了,就是通过key来查找value的操作,我们再来看看LinkHashMap的中get方法。

代码语言:javascript
复制
public V get(Object key) {
    LinkedHashMapEntry<K,V> e = (LinkedHashMapEntry<K,V>)getEntry(key);
     if (e == null)
       return null;
      //实现排序的关键方法
      e.recordAccess(this);
     return e.value;
 }

调用recordAccess()方法如下:

代码语言:javascript
复制
void recordAccess(HashMap<K,V> m) {
     LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
     if (lm.accessOrder) {
       lm.modCount++;
     remove();
       addBefore(lm.header);
     }
 }

由此可见LruCache中维护了一个集合LinkedHashMap,该LinkedHashMap是以访问顺序排序的。当调用put()方法时,就会在结合中添加元素,并调用trimToSize()判断缓存是否已满,如果满了就用LinkedHashMap的迭代器删除队尾元素,即最近最少访问的元素。当调用get()方法访问缓存对象时,就会调用LinkedHashMap的get()方法获得对应集合元素,同时会更新该元素到队头。

04

Broadcast注册方式与区别

一、Brodcast注册方式:

代码语言:javascript
复制
1、静态注册:

2、动态注册:

二、静态注册:在清单文件manifest中注册,当程序退出之后还可以收到该广播。不能控制具体某个时间点接收和不接收广播。

三、动态注册:通过代码的方式注册context.registerReceiver(broadcastReceiver),注册的同时注意在不需要接受的时候进行反注册context.unregisterReceiver(broadcastReceiver);避免内存泄漏, 动态注册可以很好的控制广播接受。

四、从Android 8.0(API 26)开始,对于大部分隐式广播(广播的对象不是针对你开发的APP),不能在manifest中声明receiver,如果需要使用隐式广播,需要使用context.registerReceiver 的方法。

05

使用Xposed为什么需要Root

Xposed框架(Xposed Framework)是一套开源的、在Android高权限模式下运行的框架服务,可以在不修改APK文件的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。是通过加载插件的形式安装的,例如微信抢红包等

Xposed通过劫持Android系统的zygote进程来加载自定义功能,就像是半路截杀,在应用运行之前就已经将我们需要的自定义内容强加在了系统进程当中。

Magisk类似Xposed,但是他是通过挂载一个与系统文件相隔离的文件系统来加载自定义内容,为系统分区打开了一个通往平行世界的入口,所有改动在那个世界Magisk分区里发生,在必要的时候却又可以被认为是(从系统分区的角度而言)没有发生过

因为Xposed需要胁持Zygote进程,所以必须root,不然拿不到权限

06

结束语

如果你有好的答案可以提交至:

https://github.com/codeegginterviewgroup/CodeEggDailyInterview

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码个蛋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ListView如何提高效率
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档