小编fin*_*usl的帖子

具有多个顶级目的地的导航图

我在业余时间实现了一个Android应用程序(在Kotlin中,但这与问题无关),我尝试使用android jetpack和新库。我有一个带有导航抽屉的活动。我尝试遵循示例向日葵应用程序。它在主要活动中使用以下组合来启用导航抽屉背后的逻辑:

appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
setSupportActionBar(findViewById(R.id.toolbar))
setupActionBarWithNavController(navController, appBarConfiguration)
Run Code Online (Sandbox Code Playgroud)

关于此代码的注意事项:在导航抽屉中单击时,此代码将自动导航到正确的片段,然后关闭抽屉并保持选中状态,等等。所有这些样板代码。那很整洁,也可以。据我了解,导航抽屉菜单项的ID必须与导航图中的片段的ID匹配,并以此方式进行连接。

遇到的问题:当我使用导航抽屉转到导航图的起始片段以外的任何片段时,它将显示一个后退按钮,而不是汉堡包项目。那不是我所期望的,我希望它仍然是汉堡包,因为导航抽屉用于在相同级别的视图之间导航,而不是彼此嵌套,对吗?如果我通过单击片段中的元素(例如,列表->详细信息)导航到任何片段的子片段,则希望有一个后退按钮,但是如果我使用导航抽屉进行导航,则不会。

现在,我将问题追溯到生成AppBarConfiguration器,该生成器读取了带有导航图的构造函数The NavGraph whose start destination should be considered the only top level destination.,通过覆盖AppBarConfiguration以返回不同的顶级目的地(而不只是导航图的起始目的地),我可以很轻松地解决此问题。

但是我的问题是,为什么会有这种行为默认?是虫子吗?如果我不这样做,是否会违反Google的某些设计准则?导航抽屉中的每个元素是否都应该与我期望的处于同一水平?我是否想使用其他解决方案?

android navigation-drawer android-navigation android-jetpack

10
推荐指数
2
解决办法
4505
查看次数

使用mock来匹配任何可变参数

我正在尝试模拟 Android 上下文以从资源 id 返回字符串。但是,我在将存根与调用匹配时遇到问题,我认为这是因为可变参数。然而,我是模拟新手,所以我可能会错过一些非常简单的东西。

我这样嘲笑上下文:

val context = mockk<Context>()
every { context.getString(any(), any()) } returns stringToReturn
Run Code Online (Sandbox Code Playgroud)

但是当在对象上调用 getString 时,它会抛出以下异常:

io.mockk.MockKException: no answer found for: Context(#1).getString(2131689544, [])
Run Code Online (Sandbox Code Playgroud)

如果它很重要,我会在被测试的类中调用与此类似的函数。formatArgs 可以为空,但不必为空:

protected fun foo(stringResource: Int, vararg formatArgs: Any) {
    val s = context.getString(errorMessageStringResource, *formatArgs)
Run Code Online (Sandbox Code Playgroud)

知道我该如何解决这个问题吗?

您可以在此处检查项目并重现异常:Github Project

android kotlin mockk

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

SonarLint 在此处使用原始布尔表达式

我有以下类属性:

class Properties {
    private Boolean enabled;

    public Boolean getEnabled() {
        return enabled;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我编写以下代码,SonarLint 会在 if 条件上给我一个警告,说“在此处使用原始布尔表达式。”。

if (!properties.getEnabled()) {
    return true;
}
// more code
Run Code Online (Sandbox Code Playgroud)

将 if 条件更改为以下内容会关闭警告。但那不太可读,那不可能是 SonarLint 想要的,或者?

if (properties.getEnabled().equals(Boolean.FALSE)) {
    return true;
}
// more code
Run Code Online (Sandbox Code Playgroud)

SonarLint 到底想让我在这里做什么?问题是什么?

java primitive-types sonarlint

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

从并行流中捕获异常

我有一堆列作为csv文件中的字符串数组.现在我想解析它们.由于这种解析需要日期解析和其他不那么快的解析技术,我正在考虑并行性(我计时,它需要一些时间).我的简单方法:

Stream.of(columns).parallel().forEach(column -> 
    result[column.index] = parseColumn(valueCache[column.index], column.type));
Run Code Online (Sandbox Code Playgroud)

列包含的ColumnDescriptor元素只有两个属性,即要解析的列索引和定义如何解析它的类型.没有其他的.result是一个Object数组,它接受结果数组.

问题是现在解析函数抛出ParseException,我进一步处理调用堆栈.既然我们在这里并行,它就不能被抛出.处理这个问题的最佳方法是什么?

我有这个解决方案,但我有点畏缩阅读它.什么是更好的方法呢?

final CompletableFuture<ParseException> thrownException = new CompletableFuture<>();
Stream.of(columns).parallel().forEach(column -> {
    try {
        result[column.index] = parseColumn(valueCache[column.index], column.type);
    } catch (ParseException e) {
        thrownException.complete(e);
    }});

if(thrownException.isDone())
    //only can be done if there is a value set.
    throw thrownException.getNow(null);
Run Code Online (Sandbox Code Playgroud)

注意:我不需要所有例外.如果我按顺序解析它们,我也只会得到一个.这样就可以了.

java parallel-processing exception-handling java-8 java-stream

7
推荐指数
2
解决办法
3769
查看次数

如何在单元测试中等待 suspendCoroutine?

我想为我的 android 应用程序编写测试。有时 viewModel 会使用 Kotlins 协程启动函数在后台执行任务。这些任务在 androidx.lifecycle 库提供的 viewModelScope 中执行。为了仍然测试这些功能,我用 Dispatchers.Unconfined 替换了默认的 android Dispatchers,它同步运行代码。

至少在大多数情况下。使用 suspendCoroutine 时, Dispatchers.Unconfined 不会被挂起并稍后恢复,而是会简单地返回。的文档Dispatchers.Unconfined揭示了原因:

[Dispatchers.Unconfined] 让协程在相应挂起函数使用的任何线程中恢复。

所以根据我的理解,协程实际上并没有被挂起,而是之后的异步函数的其余部分suspendCoroutine在调用continuation.resume. 因此测试失败。

例子:

class TestClassTest {
var testInstance = TestClass()

@Test
fun `Test with default dispatchers should fail`() {
    testInstance.runAsync()
    assertFalse(testInstance.valueToModify)
}

@Test
fun `Test with dispatchers replaced by Unconfined should pass`() {
    testInstance.DefaultDispatcher = Dispatchers.Unconfined
    testInstance.IODispatcher = Dispatchers.Unconfined
    testInstance.runAsync()
    assertTrue(testInstance.valueToModify)
}

@Test
fun `I need to also test some functions that …
Run Code Online (Sandbox Code Playgroud)

unit-testing kotlin kotlin-coroutines

6
推荐指数
2
解决办法
7296
查看次数

如何将 Javascript 导出类转换为 Kotlin/JS?

我是 JS 和 Kotlin/JS 的新手。我有以下来自示例的黑曜石插件的最小工作 Javascript 代码。它按预期工作:

var obsidian = require('obsidian');
class SomePlugin extends obsidian.Plugin {
    onload() {
        new obsidian.Notice('This is a notice!');
    }
}
module.exports = Plugin;
Run Code Online (Sandbox Code Playgroud)

我希望使用 Kotlin 来扩展这个插件,因为我了解这种语言,但是将其转换为 Kotlin/JS 时遇到一些问题。到目前为止我的方法:

可运行的项目可以在 Github 上找到。运行gradle build生成构建文件夹。它会在浏览器步骤中失败,但该步骤不是必需的。构建完成后,可以在 .js 文件中找到生成的 js 文件build\js\packages\main\kotlin\main.js

主程序.kt

@JsExport
class SomePlugin: Plugin() {
    override fun onload() {
        Notice("This is a notice!")
    }
}
@JsModule("obsidian")
@JsNonModule // required by the umd moduletype
external open class Component {
    open fun …
Run Code Online (Sandbox Code Playgroud)

javascript kotlin kotlin-js-interop kotlin-js

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

如何在Kotlin中使用Mockito模拟Lambda

我有一个Kotlin Android应用程序。有一个函数可以从后端加载合成并将其返回给回调:

getCompositons(callback: (Array<Composition>) -> Unit)
Run Code Online (Sandbox Code Playgroud)

我怎样才能使用嘲笑模拟回调。这样我就可以执行以下操作:

var callback = //mockito mock
getCompositons(callback) 
verify(callback, timeout(10000)).apply()
Run Code Online (Sandbox Code Playgroud)

我读到lambda与Java类型的函数匹配,因此我认为apply可能是调用的方法。也许我可以模拟一个函数并使用它?但是Kotlin函数接口似乎只有一种返回类型,没有参数。java.util.Function说未解决的参考函数。

任何帮助表示赞赏。

mockito kotlin

4
推荐指数
1
解决办法
1920
查看次数

找不到Android绑定适配器

请有人帮我!我快疯了,这应该工作。尝试构建Android项目时,出现以下错误消息:

Android resource linking failed
/Users/slehrbaum/StudioProjects/OneNightComps/Android/app/build/intermediates/incremental/mergeDebugResources/stripped.dir/layout/fragment_login.xml:17: error: attribute errorText (aka lehrbaum.de.onenightcomps:errorText) not found.
error: failed linking file resources.
Run Code Online (Sandbox Code Playgroud)

错误消息确实提到了errorText属性。我以这种方式在xml中使用errorText属性(此处为完整xml):

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/usernameField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/username"
        app:hintEnabled="true"
        app:errorEnabled="true"
        app:errorText="Hi"
        >
        <!--app:errorText="Please provide a username."-->
        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:autofillHints="username"
            android:inputType="text"
            android:text="@={viewModel.username}"
            />
    </com.google.android.material.textfield.TextInputLayout>
Run Code Online (Sandbox Code Playgroud)

这是我在Kotlin文件(此处为完整文件)中定义errorText的方式:

object ViewDataBindingExtensions {
    @JvmStatic
    @BindingAdapter("errorText")
    fun bindErrorText(textInputLayout: TextInputLayout, errorText: String) {
        textInputLayout.error = errorText
    }
}
Run Code Online (Sandbox Code Playgroud)

我只是不明白为什么会这样。我可以在布局文件中输入某种类型的导入信息,以说明BindingAdapter的位置吗?我的Gradle文件有问题吗?在这个问题上,我将它与GitHub项目进行了比较, 这个问题显然已经解决了,我看不出我的项目有什么区别。根据答案,我应该将Kotlin-kapt插件添加到我的Gradle构建中。我还浏览了项目的其余部分并进行了比较。无济于事。您可以在这里找到我的整个build.gradle文件以及该项目的其余部分。

请帮我!

android kotlin android-databinding androidx

2
推荐指数
1
解决办法
908
查看次数

如何避免调用相同函数的 MediatorLiveData 的所有来源?

问题介绍: 在使用MediatorLiveDataandroid自带的android jetpack的时候,我发现自己经常从各个源调用同一个函数。例如,这可能是因为,每当更新一个来源时,我都必须检查它是否有影响,或者另一个来源是否更重要。代码示例(Kotlin,但不重要):

val isHovered = MutableLiveData<Boolean>()
val isSelected = MutableLiveData<Boolean>()

val color = MediatorLiveData<Int>().apply { 
    addSource(isHovered) { updateColor() }
    addSource(isSelected) { updateColor() }
}

fun updateColor() {
    if (isHovered.value == true)
        color.value = Color.GREEN
    else if (isSelected.value == true)
        color.value = Color.RED
    else
        color.value = Color.GRAY
}
Run Code Online (Sandbox Code Playgroud)

悬停时项目为绿色,选中时为红色,未悬停时为红色,否则为灰色。当 isSelected 变为 true 时,在将颜色更改为红色之前,我还需要检查它是否处于悬停状态。此外,当 isHovering 更改为 false 时,我需要在将颜色更改为灰色之前检查它是否被选中。所以最简单的是一个函数,它考虑了所有变量并相应地设置颜色。

我的问题: 当 MediatorLiveData 从非活动状态变为活动状态时,因为视图移到了前台updateColor,对于每个更改的源,可能会多次调用该函数。这是不必要的,因为每次调用都已经考虑了所有变量。由于这个函数可能非常复杂并且可能有很多来源,有没有办法避免针对源 LiveDatas 的相同状态多次调用它?

android event-driven android-livedata android-jetpack

2
推荐指数
1
解决办法
2863
查看次数