小编Rob*_*ham的帖子

Kotlin和惯用的写法,'if not not null,else ......'基于可变值

假设我们有这个代码:

class QuickExample {

    fun function(argument: SomeOtherClass) {
        if (argument.mutableProperty != null ) {
            doSomething(argument.mutableProperty)
        } else {
            doOtherThing()
        }
    }

    fun doSomething(argument: Object) {}

    fun doOtherThing() {}
}

class SomeOtherClass {
    var mutableProperty: Object? = null
}
Run Code Online (Sandbox Code Playgroud)

与Java不同,在运行时可以单独担心空解除引用,这不能编译 - 非常正确.当然,mutableProperty在'if'中可能不再为null.

我的问题是处理这个问题的最佳方法是什么?

有一些选择很明显.在不使用任何新的Kotlin语言功能的情况下,最简单的方法显然是将值复制到随后不会更改的方法范围.

有这个:

fun function(argument: SomeOtherClass) {
    argument.mutableProperty?.let {
        doSomething(it)
        return
    }
    doOtherThing()
}
Run Code Online (Sandbox Code Playgroud)

这有一个明显的缺点,你需要提前返回或以其他方式避免执行后续代码 - 确定在某些小的情况下,但它有一股气味.

然后有这种可能性:

fun function(argument: SomeOtherClass) {
    argument.mutableProperty.let {
        when {
            it != null -> {
                doSomething(it)
            }
            else -> {
                doOtherThing() …
Run Code Online (Sandbox Code Playgroud)

android idioms kotlin

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

使用Facebook Android SDK和Proguard登录

我用Facebook Android SDK 3.0创建了一个Android应用程序.

我创建了一个工作应用程序(从Eclipse运行时).它将创建一个Facebook会话(使用com.facebook.UiLifecycleHelper)和一个登录按钮(使用com.facebook.LoginButton),以便用户可以登录Facebook.Facebook身份验证对话框正在显示,填写凭据后,登录按钮将显示用户已登录到Facebook.

所以,一切正常,但是当我正在进行发布版本(启用了Proguard)时,我得到以下异常:

E/AndroidRuntime(14690): FATAL EXCEPTION: main
E/AndroidRuntime(14690): com.facebook.FacebookException: Unable to save session.
E/AndroidRuntime(14690):    at com.facebook.Session.saveSession(Session.java:673)
E/AndroidRuntime(14690):    at com.facebook.UiLifecycleHelper.onSaveInstanceState(UiLifecycleHelper.java:124)
E/AndroidRuntime(14690):    at com.peerkesoftware.blockcrusher.MorburActivity.onSaveInstanceState(MorburActivity.java:175)
E/AndroidRuntime(14690):    at android.app.Activity.performSaveInstanceState(Activity.java:1147)
E/AndroidRuntime(14690):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1216)
E/AndroidRuntime(14690):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3253)
E/AndroidRuntime(14690):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3312)
E/AndroidRuntime(14690):    at android.app.ActivityThread.access$900(ActivityThread.java:150)
E/AndroidRuntime(14690):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1271)
E/AndroidRuntime(14690):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(14690):    at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(14690):    at android.app.ActivityThread.main(ActivityThread.java:5191)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(14690):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
E/AndroidRuntime(14690):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
E/AndroidRuntime(14690):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(14690): Caused by: java.io.NotSerializableException: com.facebook.internal.SessionTracker$CallbackWrapper
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671) …
Run Code Online (Sandbox Code Playgroud)

java android facebook-android-sdk

13
推荐指数
1
解决办法
2993
查看次数

Android,Gradle,产品口味和清单

build.gradle,我有产品口味设置:

productFlavors
{
    AlternateFlavour
    {
        applicationId "com.myapp.alternateflavour"
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在sourceSets部分中,我为这些风格使用不同的资源,资产和清单目录:

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }

    AlternateFlavour {
        manifest.srcFile 'manifest-tmp/AlternateFlavour/AndroidManifest.xml'
        java.srcDirs = ['src']
        res.srcDirs = ['res-tmp/AlternateFlavour']
        assets.srcDirs = ['assets-tmp/AlternateFlavour']
        }
   }
Run Code Online (Sandbox Code Playgroud)

好到目前为止.

在那个由部分自动生成的风味使用的清单中,我有:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myapp.myapp"
    android:versionCode="1010001"
    android:versionName="V1.1.0.1" >
Run Code Online (Sandbox Code Playgroud)

但在根项目的原始清单中如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myapp.myapp"
    android:versionCode="1010000"
    android:versionName="V1.1.0.DEBUG" >
Run Code Online (Sandbox Code Playgroud)

这会导致Gradle失败:

Error:
    Attribute manifest@versionCode value=(1010001) from AndroidManifest.xml:4:5-28
    is also present at AndroidManifest.xml:4:5-28 value=(1010000).
Attributes of <manifest> …
Run Code Online (Sandbox Code Playgroud)

android gradle android-build android-productflavors android-build-flavors

7
推荐指数
1
解决办法
3314
查看次数

Kotlin 的 'let' 加上 elvis,以及意外的 null 返回值

今天我很惊讶地发现这种明显惯用的代码失败了:

class QuickTest {

    var nullableThing: Int? = 55

    var nullThing: Int? = null

    @Test
    fun `test let behaviour`() {
        nullableThing?.let {
            print("Nullable thing was non-null")
            nullThing?.apply { print("Never happens") }
        } ?: run {
            fail("This shouldn't have run")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是因为,结合隐式返回,nullThing?.apply{...}将 null 传递给 let,因此 elvis 运算符评估 null 并运行第二个块。

这是非常可怕的检测。我们是否有超越传统的合适替代方案if/else而没有这个陷阱?

idioms kotlin

7
推荐指数
1
解决办法
2447
查看次数

当系统自动终止服务时取消Android通知

我有一个实现的应用程序MediaBrowserServiceCompat。播放音乐时,它会在前台运行,并带有媒体控制通知,告知系统不可关闭。暂停时,它不显示在前台,并且保留通知。标准的东西。

当系统自动终止该服务时,不会删除该通知。

您可以通过将应用置于非前景暂停状态,离开应用并发出以下命令来模拟此情况:

adb shell am kill com.myapp.package
Run Code Online (Sandbox Code Playgroud)

通知仍然存在。您收到此Logcat消息:

W/ActivityManager: Scheduling restart of crashed service com.myapp.package/com.myapp.package.playback.platform.AndroidMediaService
Run Code Online (Sandbox Code Playgroud)

明显的挂钩(如没有onDestroyonTaskRemoved对服务等)似乎是叫-它似乎被彻底杀死。由于该服务始于START_NOT_STICKY,我们也不会onCreate在新实例上调用它。

的部分解决方案,这是使服务粘,并取消通知时的服务恢复。但是,这可能需要花费大量时间才能真正发生,在此期间通知不起作用,因此并不理想。它还可能会产生进一步的后果。

其他应用程序似乎对此没有任何问题。

重复这种情况(暂停,退出应用)并执行命令,例如在Google Play音乐上:

adb shell am kill com.google.android.music
Run Code Online (Sandbox Code Playgroud)

或Spotify:

adb shell am kill com.spotify.music
Run Code Online (Sandbox Code Playgroud)

并且您发现他们的通知会立即消失,就像它们在拆除时被取消一样。

他们会怎么做才能做到这一点?

android android-notifications android-mediasession

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

在 MediaBrowserService.onLoadChildren 中,何时/如何提供选项包?

MediaServiceBrowseror中MediaServiceBrowserCompat,有两种方法:

public abstract void onLoadChildren (String parentId, Result<List<MediaBrowser.MediaItem>> result)

public void onLoadChildren (String parentId, Result<List<MediaBrowser.MediaItem>> result, Bundle options)

options描述为:

Bundle:从媒体浏览器发送的特定于服务的参数包。通过结果返回的信息应该受到该包内容的影响。该值绝不能为空。

我希望向(正在加载其子级的)MediaDescriptionCompat提供额外的内容,以便在第二次调用中将它们呈现出来。MediaItem

但是,仅调用第一个方法,如在 Android Auto 下测试的那样。

我需要做什么才能因options争论而被叫去?

android mediabrowserservice mediabrowserservicecompat mediabrowser

5
推荐指数
0
解决办法
500
查看次数

Android LinearGradient和奇怪的相对定位

我有以下代码和LinearGradient,它与其他所有示例看起来非常相似.

public class CustomColourBar extends View
{

public CustomColourBar( Context context, AttributeSet attribs )
{
    super( context, attribs );
}    

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    setMeasuredDimension(170, 40);
}

@Override
protected synchronized void onDraw( Canvas canvas )
{
    int height = this.getMeasuredHeight();
    int width = this.getMeasuredWidth();

    LinearGradient shader = new LinearGradient(
        0, 0, 0, height, 
        Color.RED, Color.YELLOW,
        Shader.TileMode.CLAMP );

    Paint paint = new Paint(); 
    paint.setShader(shader);
    RectF fgRect = new RectF( 0, 0, width, height);

    canvas.drawRoundRect(fgRect, 7f, 7f, paint); …
Run Code Online (Sandbox Code Playgroud)

layout android gradient

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