Ale*_*kov 5 android kotlin clean-architecture android-room android-livedata
我正在尝试将干净架构方法应用于我的项目(链接:我当前正在参考的指南)。
我正在使用Room数据库进行本地存储,并且希望它成为应用程序中的单一数据源-这意味着从网络调用中收集的所有数据都首先保存在数据库中,然后再传递给演示者。Room提供了DAO返回的LiveData,这正是我需要的。
但是,我也想使用存储库作为访问数据的单一方法。这是域层中存储库接口的示例(最抽象的一个):
interface Repository<T>{
fun findByUsername(username: String) : List<T>
fun add(entity: T): Long
fun remove(entity: T)
fun update(entity: T) : Int
}
Run Code Online (Sandbox Code Playgroud)
在这里,我遇到了问题-我需要在ViewModel中从Room的DAO获取一个LiveData,我想使用Repository实现来获取它。但是为了实现这一点,我需要:
这两个选项都具有足够的缺点:
android.arch.lifecycle.LiveData我的Repository接口,它将破坏Domain层的抽象,因为它现在取决于android体系结构库。val entities: LiveData<List<Entity>> = database.entityDao.findByUsername(username)那么我违反了所有数据访问都必须使用Reposiotry进行访问的规则,并且我将需要创建一些样板代码以与远程存储等进行同步。如何使用LiveData,Room的DAO和Clean架构模式实现单一数据源方法?
从技术上讲,您遇到了麻烦,因为您不希望同步数据获取。
fun findByUsername(username: String) : List<T>
Run Code Online (Sandbox Code Playgroud)
您希望订阅List<T>每次发生更改时都会返回一个新订阅。
fun findByUsernameWithChanges(username: String) : Subscription<List<T>>
Run Code Online (Sandbox Code Playgroud)
所以现在您可能想要做的是制作自己的订阅包装器,可以处理LiveData或Flowable. 当然,LiveData更棘手,因为你还必须给它一个 LifecycleOwner。
public interface Subscription<T> {
public interface Observer<T> {
void onChange(T t);
}
void observe(Observer<T> observer);
void clear();
}
Run Code Online (Sandbox Code Playgroud)
然后像
public class LiveDataSubscription<T> implements Subscription<T> {
private LiveData<T> liveData;
private LifecycleOwner lifecycleOwner;
private List<Observer<T>> foreverObservers = new ArrayList<>();
public LiveDataSubscription(LiveData<T> liveData) {
this.liveData = liveData;
}
@Override
public void observe(final Observer<T> observer) {
if(lifecycleOwner != null) {
liveData.observe(lifecycleOwner, new android.arch.lifecycle.Observer<T>() {
@Override
public void onChange(@Nullable T t) {
observer.onChange(t);
}
});
} else {
Observer<T> foreverObserver = new android.arch.lifecycle.Observer<T>() {
@Override
public void onChange(@Nullable T t) {
observer.onChange(t);
}
};
foreverObservers.add(foreverObserver);
liveData.observeForever(foreverObserver);
}
}
@Override
public void clear() {
if(lifecycleOwner != null) {
liveData.removeObservers(lifecycleOwner);
} else {
for(Observer<T> observer: foreverObservers) {
liveData.removeObserver(observer);
}
}
}
public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
this.lifecycleOwner = lifecycleOwner;
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用您的存储库
val subscription = repository.findByUsernameWithChanges("blah")
if(subscription is LiveDataSubscription) {
subscription.lifecycleOwner = this
}
subscription.observe { data ->
// ...
}
Run Code Online (Sandbox Code Playgroud)
当类似的问题被问到关于使用RxJava时,开发人员通常会回答,没关系,RxJava现在是语言的一部分,所以,你可以在领域层使用它。在我看来 - 你可以做任何事情,如果它对你有帮助的话,所以,如果使用 LiveData 不会产生问题 - 使用它,或者你可以使用 RxJava 或 Kotlin 协程代替。
| 归档时间: |
|
| 查看次数: |
1534 次 |
| 最近记录: |