Use ?. (and ?.let) safe operators instead of !!

This PR prevents potential NPEs, and follows Kotlin conventions more closely
by replacing the unsafe !! operator with safe ?. (or ?.let) (usually
!! would only be used very rarely, and with a good reason - there is one
place left in this PR where !! makes sense), and by replacing Java style
'if (x != null)' with Kotlin's '?.'
This commit is contained in:
melquiadess 2024-03-27 22:06:59 +00:00
parent 29b3d9e9e5
commit 70ea3e22a6
3 changed files with 97 additions and 77 deletions

View file

@ -396,16 +396,19 @@ class Godot(private val context: Context) : SensorEventListener {
}
if (host == primaryHost) {
renderView!!.startRenderer()
renderView?.startRenderer()
}
val view: View = renderView!!.view
containerLayout?.addView(
view,
renderView?.let {
containerLayout?.addView(
it.view,
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
)
}
editText.setView(renderView)
io?.setEdit(editText)
@ -448,20 +451,23 @@ class Godot(private val context: Context) : SensorEventListener {
})
} else {
// Infer the virtual keyboard height using visible area.
view.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
renderView?.view?.viewTreeObserver?.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
// Don't allocate a new Rect every time the callback is called.
val visibleSize = Rect()
override fun onGlobalLayout() {
val surfaceView = renderView!!.view
surfaceView.getWindowVisibleDisplayFrame(visibleSize)
val keyboardHeight = surfaceView.height - visibleSize.bottom
GodotLib.setVirtualKeyboardHeight(keyboardHeight)
renderView?.let {
val surfaceView = it.view
surfaceView.getWindowVisibleDisplayFrame(visibleSize)
val keyboardHeight = surfaceView.height - visibleSize.bottom
GodotLib.setVirtualKeyboardHeight(keyboardHeight)
}
}
})
}
if (host == primaryHost) {
renderView!!.queueOnRenderThread {
renderView?.queueOnRenderThread {
for (plugin in pluginRegistry.allPlugins) {
plugin.onRegisterPluginWithGodotNative()
}
@ -495,7 +501,7 @@ class Godot(private val context: Context) : SensorEventListener {
return
}
renderView!!.onActivityStarted()
renderView?.onActivityStarted()
}
fun onResume(host: GodotHost) {
@ -503,7 +509,7 @@ class Godot(private val context: Context) : SensorEventListener {
return
}
renderView!!.onActivityResumed()
renderView?.onActivityResumed()
if (mAccelerometer != null) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME)
}
@ -535,7 +541,7 @@ class Godot(private val context: Context) : SensorEventListener {
return
}
renderView!!.onActivityPaused()
renderView?.onActivityPaused()
mSensorManager.unregisterListener(this)
for (plugin in pluginRegistry.allPlugins) {
plugin.onMainPause()
@ -547,7 +553,7 @@ class Godot(private val context: Context) : SensorEventListener {
return
}
renderView!!.onActivityStopped()
renderView?.onActivityStopped()
}
fun onDestroy(primaryHost: GodotHost) {
@ -569,7 +575,7 @@ class Godot(private val context: Context) : SensorEventListener {
* Configuration change callback
*/
fun onConfigurationChanged(newConfig: Configuration) {
var newDarkMode = newConfig.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
val newDarkMode = newConfig.uiMode.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
if (darkMode != newDarkMode) {
darkMode = newDarkMode
GodotLib.onNightModeChanged()
@ -686,9 +692,7 @@ class Godot(private val context: Context) : SensorEventListener {
* This must be called after the render thread has started.
*/
fun runOnRenderThread(action: Runnable) {
if (renderView != null) {
renderView!!.queueOnRenderThread(action)
}
renderView?.queueOnRenderThread(action)
}
/**
@ -765,7 +769,7 @@ class Godot(private val context: Context) : SensorEventListener {
return mClipboard.hasPrimaryClip()
}
fun getClipboard(): String? {
fun getClipboard(): String {
val clipData = mClipboard.primaryClip ?: return ""
val text = clipData.getItemAt(0).text ?: return ""
return text.toString()
@ -782,15 +786,14 @@ class Godot(private val context: Context) : SensorEventListener {
@Keep
private fun forceQuit(instanceId: Int): Boolean {
if (primaryHost == null) {
return false
}
return if (instanceId == 0) {
primaryHost!!.onGodotForceQuit(this)
true
} else {
primaryHost!!.onGodotForceQuit(instanceId)
}
primaryHost?.let {
if (instanceId == 0) {
it.onGodotForceQuit(this)
return true
} else {
return it.onGodotForceQuit(instanceId)
}
} ?: return false
}
fun onBackPressed(host: GodotHost) {
@ -804,14 +807,14 @@ class Godot(private val context: Context) : SensorEventListener {
shouldQuit = false
}
}
if (shouldQuit && renderView != null) {
renderView!!.queueOnRenderThread { GodotLib.back() }
if (shouldQuit) {
renderView?.queueOnRenderThread { GodotLib.back() }
}
}
private fun getRotatedValues(values: FloatArray?): FloatArray? {
if (values == null || values.size != 3) {
return values
return null
}
val display =
(requireActivity().getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
@ -848,35 +851,39 @@ class Godot(private val context: Context) : SensorEventListener {
}
when (event.sensor.type) {
Sensor.TYPE_ACCELEROMETER -> {
val rotatedValues = getRotatedValues(event.values)
renderView!!.queueOnRenderThread {
GodotLib.accelerometer(
-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
)
getRotatedValues(event.values)?.let { rotatedValues ->
renderView?.queueOnRenderThread {
GodotLib.accelerometer(
-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
)
}
}
}
Sensor.TYPE_GRAVITY -> {
val rotatedValues = getRotatedValues(event.values)
renderView!!.queueOnRenderThread {
GodotLib.gravity(
-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
)
getRotatedValues(event.values)?.let { rotatedValues ->
renderView?.queueOnRenderThread {
GodotLib.gravity(
-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
)
}
}
}
Sensor.TYPE_MAGNETIC_FIELD -> {
val rotatedValues = getRotatedValues(event.values)
renderView!!.queueOnRenderThread {
GodotLib.magnetometer(
-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
)
getRotatedValues(event.values)?.let { rotatedValues ->
renderView?.queueOnRenderThread {
GodotLib.magnetometer(
-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
)
}
}
}
Sensor.TYPE_GYROSCOPE -> {
val rotatedValues = getRotatedValues(event.values)
renderView!!.queueOnRenderThread {
GodotLib.gyroscope(
rotatedValues!![0], rotatedValues[1], rotatedValues[2]
)
getRotatedValues(event.values)?.let { rotatedValues ->
renderView?.queueOnRenderThread {
GodotLib.gyroscope(
rotatedValues[0], rotatedValues[1], rotatedValues[2]
)
}
}
}
}
@ -1039,7 +1046,7 @@ class Godot(private val context: Context) : SensorEventListener {
@Keep
private fun initInputDevices() {
renderView!!.initInputDevices()
renderView?.initInputDevices()
}
@Keep

View file

@ -83,8 +83,9 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
override fun onDestroy() {
Log.v(TAG, "Destroying Godot app...")
super.onDestroy()
if (godotFragment != null) {
terminateGodotInstance(godotFragment!!.godot)
godotFragment?.let {
terminateGodotInstance(it.godot)
}
}
@ -93,22 +94,26 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
}
private fun terminateGodotInstance(instance: Godot) {
if (godotFragment != null && instance === godotFragment!!.godot) {
Log.v(TAG, "Force quitting Godot instance")
ProcessPhoenix.forceQuit(this)
godotFragment?.let {
if (instance === it.godot) {
Log.v(TAG, "Force quitting Godot instance")
ProcessPhoenix.forceQuit(this)
}
}
}
override fun onGodotRestartRequested(instance: Godot) {
runOnUiThread {
if (godotFragment != null && instance === godotFragment!!.godot) {
// It's very hard to properly de-initialize Godot on Android to restart the game
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
//
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
// releasing and reloading native libs or resetting their state somehow and clearing static data).
Log.v(TAG, "Restarting Godot instance...")
ProcessPhoenix.triggerRebirth(this)
godotFragment?.let {
if (instance === it.godot) {
// It's very hard to properly de-initialize Godot on Android to restart the game
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
//
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
// releasing and reloading native libs or resetting their state somehow and clearing static data).
Log.v(TAG, "Restarting Godot instance...")
ProcessPhoenix.triggerRebirth(this)
}
}
}
}

View file

@ -56,7 +56,9 @@ class FileAccessHandler(val context: Context) {
}
return try {
DataAccess.fileExists(storageScope, context, path!!)
path?.let {
DataAccess.fileExists(storageScope, context, it)
} ?: false
} catch (e: SecurityException) {
false
}
@ -69,20 +71,22 @@ class FileAccessHandler(val context: Context) {
}
return try {
DataAccess.removeFile(storageScope, context, path!!)
path?.let {
DataAccess.removeFile(storageScope, context, it)
} ?: false
} catch (e: Exception) {
false
}
}
internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String?, to: String?): Boolean {
internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String, to: String): Boolean {
val storageScope = storageScopeIdentifier.identifyStorageScope(from)
if (storageScope == StorageScope.UNKNOWN) {
return false
}
return try {
DataAccess.renameFile(storageScope, context, from!!, to!!)
DataAccess.renameFile(storageScope, context, from, to)
} catch (e: Exception) {
false
}
@ -106,16 +110,18 @@ class FileAccessHandler(val context: Context) {
return INVALID_FILE_ID
}
try {
val dataAccess = DataAccess.generateDataAccess(storageScope, context, path!!, accessFlag) ?: return INVALID_FILE_ID
return try {
path?.let {
val dataAccess = DataAccess.generateDataAccess(storageScope, context, it, accessFlag) ?: return INVALID_FILE_ID
files.put(++lastFileId, dataAccess)
return lastFileId
files.put(++lastFileId, dataAccess)
lastFileId
} ?: INVALID_FILE_ID
} catch (e: FileNotFoundException) {
return FILE_NOT_FOUND_ERROR_ID
FILE_NOT_FOUND_ERROR_ID
} catch (e: Exception) {
Log.w(TAG, "Error while opening $path", e)
return INVALID_FILE_ID
INVALID_FILE_ID
}
}
@ -176,7 +182,9 @@ class FileAccessHandler(val context: Context) {
}
return try {
DataAccess.fileLastModified(storageScope, context, filepath!!)
filepath?.let {
DataAccess.fileLastModified(storageScope, context, it)
} ?: 0L
} catch (e: SecurityException) {
0L
}