我目前正在重构我的代码,将ViewModel包含在android.arch库提供的LiveData中.我有一个简单的活动,可以将密码更改请求发送到服务器,并根据HTTP响应代码执行操作.
为此,我创建了一个类,它扩展了ViewModel的数据和一个存储库类来调用服务器.我的ViewModel类有一个MutableLiveData字段,我使用.observe(...)方法从我的活动订阅.问题是.observe(...)中的代码在配置更改(即屏幕旋转)后一直触发,我不明白为什么.
以下是ViewModel,Repository和Activity类的代码:
ChangePasswordViewModel
public class ChangePasswordViewModel extends ViewModel{
private MutableLiveData<Integer> responseCode;
private PasswordChangeRepository passwordChangeRepository;
public ChangePasswordViewModel() {
responseCode = new MutableLiveData<>();
passwordChangeRepository = new PasswordChangeRepositoryImpl();
}
public MutableLiveData<Integer> responseCodeLiveData() {
return responseCode;
}
public void sendChangePasswordRequest(String newPassword){
passwordChangeRepository.changePassword(newPassword, passChangeCallback());
}
// Callback that fires after server sends a response
private Callback passChangeCallback(){
...
responseCode.postValue(serverResponse)
...
}
Run Code Online (Sandbox Code Playgroud)
PasswordChangeRepository
public class PasswordChangeRepositoryImpl {
public void changePassword(String newPassword, Callback<Void> callback){
//Sending new password to server and processing response in callback
ServerCalls.changePassword(newPassword, callback); …Run Code Online (Sandbox Code Playgroud) 我在MySQL中有两个简单的表
User ---(one-to-many)--- Expense
Run Code Online (Sandbox Code Playgroud)
我正在使用Spring JPA生成这两个实体。费用包含“ user_id”外键字段,该字段引用用户表中的“ id”字段。
我在请求中使用JSON填充表格
User
{"id":1, "username":"user"}
Expense
{
"id":1,
"user_id":1, <--- this value is not null in MySQL
"expense":"expense"
}
Run Code Online (Sandbox Code Playgroud)
调用API时,我已经具有user_id值,并且我不想传递整个对象。
有没有办法告诉Spring这是引用“用户”表中“ id”列的INTEGER FOREIGN KEY?
我在网上找到的所有示例仅显示了如何通过在JSON中传递整个“ User”对象来实现。
我当前的实现:
@Entity
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private int id;
private String username;
}
@Entity
public class Car{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private int id; …Run Code Online (Sandbox Code Playgroud) 我正在尝试将干净架构方法应用于我的项目(链接:我当前正在参考的指南)。
我正在使用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架构模式实现单一数据源方法?
android kotlin clean-architecture android-room android-livedata
我正在处理需要初始化 Firebase 令牌的 Android 项目。主要使用 Kotlin 协程,我想逐行实现代码,但由于无法同步请求 Firebase 令牌,我想出了使用OnCompleteListener以下函数进行包装的解决方案:
private suspend fun fcmCallbackSuspendWrapper(block: (OnCompleteListener<InstanceIdResult>) -> Unit)
= suspendCancellableCoroutine<Task<InstanceIdResult>> { cont ->
block(OnCompleteListener { response ->
cont.resume(response)
})
}
Run Code Online (Sandbox Code Playgroud)
它基本上会阻塞当前线程,直到任务调用回调为止。然后我通过以下方式在我的代码中应用所述函数:
val fcmInstance = fcmCallbackSuspendWrapper { listener ->
fireBaseInstanceIdProvider
.provide() // Returns Firebase instance
.instanceId // Returns Task<InstanceIdResult>
.addOnCompleteListener(listener) // Sets listener to block current thread until completed
}
Run Code Online (Sandbox Code Playgroud)
但现在我需要在上面的代码中添加单元测试,这里我遇到了几个问题:
@Mock lateinit var instanceIdResultTaskMock: Task<InstanceIdResult>
@Mock lateinit var fireBaseInstanceIdProviderMock: Provider<FirebaseInstanceId>
@Mock lateinit var firebaseInstanceIdMock: FirebaseInstanceId
...
Mockito.`when`(fireBaseInstanceIdProviderMock.provide()).thenReturn(firebaseInstanceIdMock)
Mockito.`when`(firebaseInstanceIdMock.instanceId).thenReturn(instanceIdResultTaskMock)
Run Code Online (Sandbox Code Playgroud)
但由于Task<InstanceIdResult> …