ITPub博客

首页 > 移动开发 > ANDROID > 阿里Android三面真题,想进阿里关于LiveData的这三个问题你至少得答出来

阿里Android三面真题,想进阿里关于LiveData的这三个问题你至少得答出来

原创 ANDROID 作者:南方吴彦祖_蓝斯 时间:2020-11-23 15:41:18 0 删除 编辑

今天一起来看看阿里面试真题LiveData的有关问题:

  • LiveData 是什么?
  • LiveData 为什么被设计出来,解决了什么问题?
  • 说说LiveData原理。

LiveData 是什么?

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

官方介绍如下,其实说的比较清楚了,主要作用在两点:

  • 数据存储器类。也就是一个用来存储数据的类。

  • 可观察。这个数据存储类是可以观察的,也就是比一般的数据存储类多了这么一个功能,对于数据的变动能进行响应。

主要思想就是用到了 观察者模式思想,让观察者和被观察者解耦,同时还能感知到数据的变化,所以一般被用到ViewModel中, ViewModel负责触发数据的更新,更新会通知到 LiveData,然后LiveData再通知活跃状态的观察者。

        var liveData = MutableLiveData<String>()
        liveData.observe(this, object : Observer<String> {
            override fun onChanged(t: String?) {
            }
        })
        liveData.setVaile("xixi")
        //子线程调用
        liveData.postValue("test")

LiveData 为什么被设计出来,解决了什么问题?

LiveData作为一种观察者模式设计思想,常常被和 Rxjava一起比较,观察者模式的最大好处就是事件发射的上游 和 接收事件的下游 互不干涉,大幅降低了互相持有的依赖关系所带来的 强耦合性

其次,LiveData还能无缝衔接到 MVVM架构中,主要体现在其可以感知到 Activity等生命周期,这样就带来了很多好处:

  • 不会发生内存泄漏 观察者会绑定到  Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理。

  • 不会因 Activity 停止而导致崩溃 如果观察者的生命周期处于 非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。

  • 自动判断生命周期并回调方法 如果观察者的生命周期处于  STARTED或  RESUMED状态,则 LiveData 会认为该观察者处于活跃状态,就会调用 onActive方法,否则,如果 LiveData 对象没有任何活跃观察者时,会调用  onInactive()方法。

说说LiveData原理。

说到原理,其实就是两个方法:

  • 订阅方法,也就是 observe方法。通过该方法把订阅者和被观察者关联起来,形成观察者模式。

简单看看源码:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        //...
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }
      public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> entry = get(key);
        if (entry != null) {
            return entry.mValue;
        }
        put(key, v);
        return null;
    }

这里 putIfAbsent方法是讲生命周期相关的 wrapper和观察者 observer作为key和value存到了 mObservers中。

  • 回调方法,也就是 onChanged方法。通过改变存储值,来通知到观察者也就是调用 onChanged方法。从改变存储值方法 setValue看起:
@MainThreadprotected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);}private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    //...
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;}private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);}

这一套下来逻辑还是比较简单的,遍历刚才的map—— mObservers,然后找到观察者 observer,如果观察者不在活跃状态(活跃状态,也就是可见状态,处于 STARTED 或 RESUMED状态),则直接返回,不去通知。否则正常通知到观察者的onChanged方法。

当然,如果想任何时候都能监听到,都能获取回调,调用 observeForever方法即可。

总结

讲一下大厂面试一些必备的技能

1. 一般情况下第一轮都是基础面试,需要扎实的基础

  • 最常用的Android 基础知识
  • Java 基础知识
  • 了解一些 常用东西的原理,例如:handler, thread 等
  • 项目中的技术点

2. 第二轮的时候需要了解更深层次的东西

  • Android 事件分发机制原理
  • Android 绘图机制原理
  • WindowManager 的相关知识
  • 进程间传输方式
  • Java 内存管理机制

3. 能进入第三轮基本没什么问题,但是要注意以下问题

  • 该轮一般是 老大或者部门负责人,问的问题一般都看 深度与广度

  • 当问及薪水的时候,要说一个合适的,小公司随意,大公司一定要慎重,当心里没底的时候,可以告诉对方,让对方给一个合理的薪资。一般都是在原工资基础之上增长,听猎头说一般涨幅都在15%-30%,超 NB 的可以要30%及以上,如果感觉自己还不错的,挺厉害的,建议最高20%,一般人就定在15% 左右最靠谱。公司内部一般有一套机制,根据公司情况而定。

  • 我们的面试原则就是拿到合理薪资,得到 offer

  • 个人发展情况,这个问题很难回答,如果和公司方向不符合,极有可能和公司无缘。建议多试探性的问问公司缺少什么,你能否给予公司对应的东西。当然对于有自我追求的人,那可以放心大胆的提。我的方向就是架构师,哈哈哈,挺极端的,别学我哦。我感觉选择都是双向的,因此我知道自己需要的是什么。

  • 你最擅长什么UI 还是其他什么?这个问题更不好回答。你要说你擅长 UI,是不是意味着你其他能力就不行?虽然我不知道面试官的用意,但是我能感觉到,这个问题不是那么好回答,我会回答说自己都行,来什么业务接什么需求。可能回答不太好,总之和公司的职位吻合就行,这样总不至于出错吧。

那么该如何复习?

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一下我面试期间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《Android开发七大模块核心知识笔记》

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全。

1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69983917/viewspace-2736100/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
不定期分享自己开发几年来收录整理的几十套腾讯、头条、阿里、美团等公司19年的面试题,其中把技术点整理成了视频和PDF,包含知识脉络 + 诸多细节,获取这些安卓资料请加 WX:X1524478394

注册时间:2020-09-15

  • 博文量
    50
  • 访问量
    21080