Проблема логических аргументов при создании действия настроек - PullRequest
0 голосов
/ 05 декабря 2018

После создания операции для страницы настроек я заметил, что mCurrentValue !== value в if (mCurrentValue !== value) вернул предупреждение:

Равенство идентичности для аргументов типов Boolean?и Boolean может быть нестабильным из-за неявного бокса

Я попытался разрешить это предупреждение, добавив ? рядом с Boolean в override fun onXchange(value:Boolean) {, но затем вернулась следующая ошибка:

'onXchange' ничего не отменяет

Есть идеи, как решить эту проблему?

Класс активности

import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.preference.PreferenceManager
import android.support.v7.app.AppCompatActivity
import android.view.MenuItem

class MySettingsActivity : AppCompatActivity(), MySettingsFragment.PreferenceXchangeListener {
    private var mCurrentValue: Boolean? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        mCurrentValue = mSharedPreferences.getBoolean("preference_a", false)
        if (mCurrentValue as Boolean)
        {
            setTheme(R.style.MyDarkAppCompatTheme)
        }
        else
        {
            setTheme(R.style.MyLightAppCompatTheme)
        }
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_mysettings)

        val settingsFragment = MySettingsFragment()
        supportFragmentManager
                .beginTransaction()
                .replace(R.id.settings_container, settingsFragment)
                .commit()

        val myActionBar = actionBar

        if (myActionBar != null)
        {
            myActionBar.setTitle(R.string.settings)
            myActionBar.setBackgroundDrawable(ColorDrawable(Color.BLACK))
            myActionBar.setDisplayHomeAsUpEnabled(true)
            myActionBar.setDisplayShowHomeEnabled(true)
            myActionBar.setHomeAsUpIndicator(resources.getDrawable(R.drawable.ic_arrow_back_white, null))
        }
    }

    override fun onXchange(value:Boolean?) {
        if (mCurrentValue !== value) {
            mCurrentValue = value
            recreate()
        }
    }


    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
                val intent = parentActivityIntent
                intent?.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                onBackPressed()
                return true
            }

            else ->
                return super.onOptionsItemSelected(item)
        }
    }
}

Фрагмент класса

class MySettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        addPreferencesFromResource(R.xml.app_preferences)

        val mCheckBoxPreference = findPreference("preference_a") as CheckBoxPreference
        mCheckBoxPreference.onPreferenceChangeListener = this
    }

    private var mPreferenceXchangeListener: PreferenceXchangeListener? = null

    interface PreferenceXchangeListener {
        fun onXchange(value:Boolean)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)

        try
        {
            mPreferenceXchangeListener = context as MySettingsFragment.PreferenceXchangeListener
        }
        catch (e:ClassCastException) {
            Log.e(TAG, "onAttach::::: PreferenceXchangeListener must be set in parent Activity")
        }
    }

    override fun onPreferenceChange(preference: Preference, newValue:Any):Boolean {
        val preferenceKey = preference.key

        if (preferenceKey == "preference_a")
        {
            (preference as CheckBoxPreference).isChecked = newValue as Boolean

            mPreferenceXchangeListener!!.onXchange(newValue)
            return true
        }

        return false
    }

    companion object {
        private val TAG = MySettingsFragment::class.java.simpleName
    }
}

1 Ответ

0 голосов
/ 05 декабря 2018

Итак, сначала я могу объяснить проблему, которую она описывает.Давайте предложим очень надуманный сценарий:

BooleanProvider.java

class BooleanProvider {
    @NonNull Boolean wrapMyBoolean(boolean state) {
        return new Boolean(state);
    }
}

BooleanProviderTest.kt

class BooleanProviderTest {
    @Test fun `it returns a true value when true is provided`() {
        assertSame(BooleanProvider().wrapMyBoolean(true), true)
    }
}

Этоtest на самом деле не пройдёт, потому что экземпляры Boolean не совпадают.В коде Java мы инициализировали новый экземпляр Boolean (а не статически определенные экземпляры Boolean.TRUE и Boolean.FALSE, которые вы получите, когда примитив автоматически упакован в java.lang.Boolean).Поэтому, чтобы избежать потенциально неожиданного результата, рекомендуется не сравнивать эти типы по ссылкам.

Самое простое решение - просто изменить тест на равенство на != вместо !==.Это будет выполнять тестирование на равенство идентичности, а не тестирование на равенство ссылок, и будет обрабатывать нулевое значение с любой стороны соответственно.В любом случае это то, что вам нужно в 99% случаев.

Во-вторых, вы также можете просто объявить mCurrentValue как ненулевой тип и присвоить ему значение по умолчанию, если вам не нужно обрабатыватьнулевое значение определенным образом.Просто объявите это как:

private var mCurrentValue: Boolean = false // false is the default here
...