假设我们有这个代码:
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) 我用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) 在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
今天我很惊讶地发现这种明显惯用的代码失败了:
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而没有这个陷阱?
我有一个实现的应用程序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)
明显的挂钩(如没有onDestroy,onTaskRemoved对服务等)似乎是叫-它似乎被彻底杀死。由于该服务始于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)
并且您发现他们的通知会立即消失,就像它们在拆除时被取消一样。
他们会怎么做才能做到这一点?
在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
我有以下代码和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)