【Jetpack】LiveData一些容易被忽视的功能

17 篇文章 0 订阅
13 篇文章 0 订阅

前言

LiveData平时经常使用,但是仅限于在页面上oberver注册一个观察者,在ViewModel里调用一下setValue、postValue仅此而已,今天决定过一遍LiveData库,发现了几个不常用但是却很有用的东西。

LiveData核心库有两个:lifecycle-livedatalifecycle-livedata-core

微信截图_20220513101852.png

LiveData.java

这是LiveData的核心类,所有主要逻辑均位于此

在这里发现了这个observeForever,这个方法很少用,调用此方法注册的观察者,将始终处于激活状态,页面Pause、Destroy状态对他无效,所以不用的时候需要手动调用removeObserver。有些时候需要我们在页面处于Pause状态时,也能收到LiveData发送的数据,那observeForever就派上用场了。

public void observeForever(@NonNull Observer<? super T> observer) {
   ...
}

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
    ...
}

@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner) {
    ...
    一步移除页面上所有观察者
} 

MediatorLiveData.java

  • MediatorLiveData.addSource

通过addSource可以添加多个LiveData源进来,只要其中有一个发射数据,MediatorLiveData就会触发并转发这个数据,当我们需要观察多个源时,可以考虑一下,能否用MediatorLiveData收拢成一个发射源

  • MediatorLiveData.removeSource

随时可以删除已经添加过的输入源

 LiveData  liveData1 = ...;
   LiveData  liveData2 = ...;
  
   MediatorLiveData  liveDataMerger = new MediatorLiveData<>();
   liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
   liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
   
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
    Source<?> source = mSources.remove(toRemote);
    if (source != null) {
        source.unplug();
    }
} 

Transformations.java

  • Transformations.distinctUntilChanged

经过distinctUntilChanged处理过的LiveData 遇到连续多次发射同一个值时,将自动拦截屏蔽和上一次发射值重复的值,去重防抖动利器

 MutableLiveData source = new MutableLiveData<Integer>()
   MutableLiveData outputSource = Transformations.distinctUntilChanged(source) 
  • Transformations.map

根据指定的Function,可以将原始的LiveData的发射值类型,转换成另一个类型的LiveData

public static <X, Y> LiveData<Y> map(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, Y> mapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        @Override
        public void onChanged(@Nullable X x) {
            result.setValue(mapFunction.apply(x));
        }
    });
    return result;
} 
  • Transformations.switchMap

这个函数的逻辑非常的绕,我还没找到一句话说明白的方式,暂且将函数源码以及官方调用这个函数的示例贴在这里,大家一起理解理解

public static <X, Y> LiveData<Y> switchMap(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        LiveData<Y> mSource;

        @Override
        public void onChanged(@Nullable X x) {
            LiveData<Y> newLiveData = switchMapFunction.apply(x);
            if (mSource == newLiveData) {
                return;
            }
            if (mSource != null) {
                result.removeSource(mSource);
            }
            mSource = newLiveData;
            if (mSource != null) {
                result.addSource(mSource, new Observer<Y>() {
                    @Override
                    public void onChanged(@Nullable Y y) {
                        result.setValue(y);
                    }
                });
            }
        }
    });
    return result;
} 
class UserViewModel extends AndroidViewModel {
    MutableLiveData<String> nameQueryLiveData = ...

    LiveData<List<String>> getUsersWithNameLiveData() {
        return Transformations.switchMap(
            nameQueryLiveData,
                name -> myDataSource.getUsersWithNameLiveData(name));
    }

    void setNameQuery(String name) {
        this.nameQueryLiveData.setValue(name);
    }
} 

前言

LiveData平时经常使用,但是仅限于在页面上oberver注册一个观察者,在ViewModel里调用一下setValue、postValue仅此而已,今天决定过一遍LiveData库,发现了几个不常用但是却很有用的东西。

LiveData核心库有两个:lifecycle-livedatalifecycle-livedata-core

微信截图_20220513101852.png

LiveData.java

这是LiveData的核心类,所有主要逻辑均位于此

在这里发现了这个observeForever,这个方法很少用,调用此方法注册的观察者,将始终处于激活状态,页面Pause、Destroy状态对他无效,所以不用的时候需要手动调用removeObserver。有些时候需要我们在页面处于Pause状态时,也能收到LiveData发送的数据,那observeForever就派上用场了。

public void observeForever(@NonNull Observer<? super T> observer) {
   ...
}

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
    ...
}

@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner) {
    ...
    一步移除页面上所有观察者
} 

MediatorLiveData.java

  • MediatorLiveData.addSource

通过addSource可以添加多个LiveData源进来,只要其中有一个发射数据,MediatorLiveData就会触发并转发这个数据,当我们需要观察多个源时,可以考虑一下,能否用MediatorLiveData收拢成一个发射源

  • MediatorLiveData.removeSource

随时可以删除已经添加过的输入源

 LiveData  liveData1 = ...;
   LiveData  liveData2 = ...;
  
   MediatorLiveData  liveDataMerger = new MediatorLiveData<>();
   liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
   liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
   
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
    Source<?> source = mSources.remove(toRemote);
    if (source != null) {
        source.unplug();
    }
} 

Transformations.java

  • Transformations.distinctUntilChanged

经过distinctUntilChanged处理过的LiveData 遇到连续多次发射同一个值时,将自动拦截屏蔽和上一次发射值重复的值,去重防抖动利器

 MutableLiveData source = new MutableLiveData<Integer>()
   MutableLiveData outputSource = Transformations.distinctUntilChanged(source) 
  • Transformations.map

根据指定的Function,可以将原始的LiveData的发射值类型,转换成另一个类型的LiveData

public static <X, Y> LiveData<Y> map(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, Y> mapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        @Override
        public void onChanged(@Nullable X x) {
            result.setValue(mapFunction.apply(x));
        }
    });
    return result;
} 
  • Transformations.switchMap

这个函数的逻辑非常的绕,我还没找到一句话说明白的方式,暂且将函数源码以及官方调用这个函数的示例贴在这里,大家一起理解理解

public static <X, Y> LiveData<Y> switchMap(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        LiveData<Y> mSource;

        @Override
        public void onChanged(@Nullable X x) {
            LiveData<Y> newLiveData = switchMapFunction.apply(x);
            if (mSource == newLiveData) {
                return;
            }
            if (mSource != null) {
                result.removeSource(mSource);
            }
            mSource = newLiveData;
            if (mSource != null) {
                result.addSource(mSource, new Observer<Y>() {
                    @Override
                    public void onChanged(@Nullable Y y) {
                        result.setValue(y);
                    }
                });
            }
        }
    });
    return result;
} 
class UserViewModel extends AndroidViewModel {
    MutableLiveData<String> nameQueryLiveData = ...

    LiveData<List<String>> getUsersWithNameLiveData() {
        return Transformations.switchMap(
            nameQueryLiveData,
                name -> myDataSource.getUsersWithNameLiveData(name));
    }

    void setNameQuery(String name) {
        this.nameQueryLiveData.setValue(name);
    }
} 

前言

LiveData平时经常使用,但是仅限于在页面上oberver注册一个观察者,在ViewModel里调用一下setValue、postValue仅此而已,今天决定过一遍LiveData库,发现了几个不常用但是却很有用的东西。

LiveData核心库有两个:lifecycle-livedatalifecycle-livedata-core

微信截图_20220513101852.png

LiveData.java

这是LiveData的核心类,所有主要逻辑均位于此

在这里发现了这个observeForever,这个方法很少用,调用此方法注册的观察者,将始终处于激活状态,页面Pause、Destroy状态对他无效,所以不用的时候需要手动调用removeObserver。有些时候需要我们在页面处于Pause状态时,也能收到LiveData发送的数据,那observeForever就派上用场了。

public void observeForever(@NonNull Observer<? super T> observer) {
   ...
}

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
    ...
}

@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner) {
    ...
    一步移除页面上所有观察者
} 

MediatorLiveData.java

  • MediatorLiveData.addSource

通过addSource可以添加多个LiveData源进来,只要其中有一个发射数据,MediatorLiveData就会触发并转发这个数据,当我们需要观察多个源时,可以考虑一下,能否用MediatorLiveData收拢成一个发射源

  • MediatorLiveData.removeSource

随时可以删除已经添加过的输入源

 LiveData  liveData1 = ...;
   LiveData  liveData2 = ...;
  
   MediatorLiveData  liveDataMerger = new MediatorLiveData<>();
   liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
   liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
   
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
    Source<?> source = mSources.remove(toRemote);
    if (source != null) {
        source.unplug();
    }
} 

Transformations.java

  • Transformations.distinctUntilChanged

经过distinctUntilChanged处理过的LiveData 遇到连续多次发射同一个值时,将自动拦截屏蔽和上一次发射值重复的值,去重防抖动利器

 MutableLiveData source = new MutableLiveData<Integer>()
   MutableLiveData outputSource = Transformations.distinctUntilChanged(source) 
  • Transformations.map

根据指定的Function,可以将原始的LiveData的发射值类型,转换成另一个类型的LiveData

public static <X, Y> LiveData<Y> map(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, Y> mapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        @Override
        public void onChanged(@Nullable X x) {
            result.setValue(mapFunction.apply(x));
        }
    });
    return result;
} 
  • Transformations.switchMap

这个函数的逻辑非常的绕,我还没找到一句话说明白的方式,暂且将函数源码以及官方调用这个函数的示例贴在这里,大家一起理解理解

public static <X, Y> LiveData<Y> switchMap(
        @NonNull LiveData<X> source,
        @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        LiveData<Y> mSource;

        @Override
        public void onChanged(@Nullable X x) {
            LiveData<Y> newLiveData = switchMapFunction.apply(x);
            if (mSource == newLiveData) {
                return;
            }
            if (mSource != null) {
                result.removeSource(mSource);
            }
            mSource = newLiveData;
            if (mSource != null) {
                result.addSource(mSource, new Observer<Y>() {
                    @Override
                    public void onChanged(@Nullable Y y) {
                        result.setValue(y);
                    }
                });
            }
        }
    });
    return result;
} 
class UserViewModel extends AndroidViewModel {
    MutableLiveData<String> nameQueryLiveData = ...

    LiveData<List<String>> getUsersWithNameLiveData() {
        return Transformations.switchMap(
            nameQueryLiveData,
                name -> myDataSource.getUsersWithNameLiveData(name));
    }

    void setNameQuery(String name) {
        this.nameQueryLiveData.setValue(name);
    }
} 

文末

我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。

需要的小伙伴私信【学习】我免费分享给你,以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持,需要的自己领取)

直接点击文末小卡片可以领取哦!

Android学习PDF+架构视频+面试文档+源码笔记

部分资料一览:

  • 330页PDF Android学习核心笔记(内含8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT大厂面试题(有解析)

领取地址:

点击下方卡片免费领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值