小编Ale*_*kov的帖子

Android实时数据 - 观察配置更改后始终触发

我目前正在重构我的代码,将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)

android android-lifecycle android-livedata

10
推荐指数
1
解决办法
3563
查看次数

JPA外键不正确

我在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)

spring hibernate jpa

6
推荐指数
1
解决办法
290
查看次数

Android:在DAO中使用Room数据库和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实现来获取它。但是为了实现这一点,我需要:

  1. 更改存储库方法findByUsername以返回LiveData>
  2. 或直接从ViewModel完全跳过存储库实现中调用Room的DAO

这两个选项都具有足够的缺点:

  1. 如果我汇入 android.arch.lifecycle.LiveData我的Repository接口,它将破坏Domain层的抽象,因为它现在取决于android体系结构库。
  2. 如果我直接在ViewModel中调用Room的DAO,val entities: LiveData<List<Entity>> = database.entityDao.findByUsername(username)那么我违反了所有数据访问都必须使用Reposiotry进行访问的规则,并且我将需要创建一些样板代码以与远程存储等进行同步。

如何使用LiveData,Room的DAO和Clean架构模式实现单一数据源方法?

android kotlin clean-architecture android-room android-livedata

5
推荐指数
2
解决办法
1534
查看次数

Kotlin 协程中模拟 Android Firebase 任务

我正在处理需要初始化 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> …

android unit-testing kotlin

4
推荐指数
2
解决办法
2383
查看次数