Unsucceedable cast when declaring CheckBoxPreference - android

After declaring a CheckboxPreference in my activity for my app's settings, a warning appears for as in the line 'val mCheckBoxPreference = findPreference("preference_a") as CheckBoxPreference'. What should be done so that the cast does succeed?
This cast can never succeed
app_preferences.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="preference_a"
android:defaultValue="false"
android:title="Preference A"/>
</PreferenceScreen>
fragment class
import android.content.Context
import android.os.Bundle
import android.preference.CheckBoxPreference
import android.preference.Preference
import android.support.v7.preference.PreferenceFragmentCompat
import android.util.Log
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
}
// declaring PreferenceXchangeListener
private var mPreferenceXchangeListener: PreferenceXchangeListener? = null
// declaring PreferenceXchangeListener in order to communicate with Activities
interface PreferenceXchangeListener {
fun onXchange(value:Boolean)
}
override fun onAttach(context: Context) {
super.onAttach(context)
// on attach - assign parent Activity as PreferenceXchangeListener
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
// executing parent Activity's callback with the new value
mPreferenceXchangeListener!!.onXchange(newValue)
return true
}
return false
}
companion object {
private val TAG = MySettingsFragment::class.java.simpleName
}
}
activity class
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))
}
}
override fun onXchange(value:Boolean) {
if (value !== mCurrentValue)
{
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)
}
}
companion object {
private val TAG = MySettingsActivity::class.java.simpleName
}
}

TL;DR You have to change the import to android.support.v7.preference.CheckBoxPreference.
There are two versions of CheckBoxPreference:
android.preference.CheckBoxPreference, which was added in API level 1 and has android.preference.Preference as ancestor class
android.support.v7.preference.CheckBoxPreference which belongs to the support library and has android.support.v7.preference.Preference as ancestor class
Your Fragment extends from PreferenceFragmentCompat, so findPreference() will return a android.support.v7.preference.Preference. Since you can't cast support Preference classes to their non support equivalents, Android Studio is showing the error message "This cast can never succeed" when you attempt to cast to the non support CheckBoxPreference.

Related

Why is view null despite called in viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) in viewPager2's fragment?

We have a random crash on production in this class when accessing the binding at line 10 :
class BulletinFragment : Fragment(R.layout.fragment_bulletins) {
private val bulletinViewModel: BulletinsViewModel by viewModel()
private val binding by viewBinding(FragmentBulletinsBinding::bind)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
bulletinViewModel.switchState.collect {
binding.bulletinLiveNotificationsBanner.switch.isSelected = it
}
}
}
}
}
viewModel is provided by Koin, and the binding delegate is Zhuiden's one from here
class FragmentViewBindingDelegate<T : ViewBinding>(
val fragment: Fragment,
val viewBindingFactory: (View) -> T
) : ReadOnlyProperty<Fragment, T> {
private var _binding: T? = null
init {
fragment.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner ->
viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
_binding = null
}
})
}
}
})
}
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
val binding = _binding
if (binding != null) {
return binding
}
val lifecycle = fragment.viewLifecycleOwner.lifecycle
if (!lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) {
throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed.")
}
return viewBindingFactory(thisRef.requireView()).also { _binding = it }
}
}
fun <T : ViewBinding> Fragment.viewBinding(viewBindingFactory: (View) -> T) =
FragmentViewBindingDelegate(this, viewBindingFactory)
inline fun <T : ViewBinding> AppCompatActivity.viewBinding(
crossinline bindingInflater: (LayoutInflater) -> T
): Lazy<T> {
return lazy(LazyThreadSafetyMode.NONE) {
bindingInflater.invoke(layoutInflater)
}
}
This fragment is called within a viewPager2:
class CartPagerAdapter(fragment: Fragment) : FragmentStateAdapter(
fragment.childFragmentManager,
fragment.viewLifecycleOwner.lifecycle
) {
val firstFragment = FirstFragment()
val secondFragment = SecondFragment()
override fun createFragment(position: Int): Fragment = when (position) {
Tab.FIRST_TAB.tabIndex -> firstFragment
Tab.SECOND_TAB.tabIndex -> secondFragment
Tab.THIRD_TAB.tabIndex -> BulletinFragment()
else -> error("The fragment position should in 0 < x < 2 but was '$position'")
}
fun handleDeeplink(deeplink: Uri) {
when (deeplink.host) {
FIRST_TAB_DEEPLINK_HOST -> firstFragment.handleDeeplink(deeplink)
SECOND_TAB_DEEPLINK_HOST -> secondFragment.handleDeeplink(deeplink)
}
}
override fun getItemCount(): Int = 3
}
class CartHomeFragment : Fragment(R.layout.fragment_cart_home), CartHomeContract.View {
private var tabLayoutMediator: TabLayoutMediator? = null
private val args: CartHomeFragmentArgs by navArgs()
private var initTab: Int? = null
// betSlip needs to scroll to top when displaying QrCodes tab (set when moving to QrCode tab after validating cart)
private val pagerAdapter: CartPagerAdapter by adapter { CartPagerAdapter(this) }
private val binding by viewBinding(FragmentCartHomeBinding::bind)
private val scope
get() = viewLifecycleOwner.lifecycleScope
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initTab = args.tabIndex
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initialize()
}
override fun onDestroyView() {
tabLayoutMediator?.detach()
tabLayoutMediator = null
super.onDestroyView()
}
private fun initialize() {
scope.launch {
binding.fragmentCartHomeViewPager.run {
adapter = pagerAdapter
setPagerCurrentItem(this)
offscreenPageLimit = 2
}
tabLayoutMediator = TabLayoutMediator(binding.cartTabLayout, binding.fragmentCartHomeViewPager) { tab, position ->
val (title, contentDesc) = with(getTab(position)) { getString(title) to getString(contentDesc) }
tab.text = title
tab.contentDescription = contentDesc
}
tabLayoutMediator?.attach()
}
}
private fun setPagerCurrentItem(viewPager: ViewPager2) {
val initialIntent = arguments?.getParcelable<Intent>(NavController.KEY_DEEP_LINK_INTENT)
initialIntent?.data?.let {
pagerAdapter.handleDeeplink(it)
viewPager.setCurrentItemForDeeplink(it.host)
initialIntent.data = null
} ?: run {
initTab?.let {
viewPager.setCurrentItem(it, false)
initTab = null
}
}
}
fun getTab(index: Int): Tab {
return Tab.values()[index]
}
private fun ViewPager2.setCurrentItemForDeeplink(deeplink: String?) {
setCurrentItem(Tab.getTabIndexForDeeplink(deeplink), false)
}
companion object {
const val FIRST_TAB_DEEPLINK_HOST = "first"
const val SECOND_TAB_DEEPLINK_HOST = "second"
const val THIRD_TAB_DEEPLINK_HOST = "third"
val DEFAULT_TAB: Tab = Tab.FIRST_TAB
const val SECOND_TAB_DEEPLINK_DETAILS_PATH = "/details"
}
}
enum class Tab(#StringRes val title: Int, #StringRes val contentDesc: Int, val deeplink: String) {
FIRST_TAB(R.string.first_tab_tab_title, R.string.a11y_first_tab, FIRST_TAB_DEEPLINK_HOST),
SECOND_TAB(R.string.second_tab_title, R.string.a11y_second_tab, SECOND_TAB_DEEPLINK_HOST),
THIRD_TAB(R.string.third_tab_title, R.string.a11y_third_tab, THIRD_TAB_DEEPLINK_HOST);
val tabIndex: Int = ordinal
companion object {
fun getTabIndexForDeeplink(deeplink: String?): Int =
(values().firstOrNull { it.deeplink == deeplink }
?: DEFAULT_TAB)
.tabIndex
}
}
In the BulletinFragment, I know that the repeatOnLifecycle block seems useless here but we need it for some reason that is not necessary to explain here. I just would like to understand what is wrong with this piece of code. Actually, we get from crashlytics the following crash happening randomly (rare enough to not succeed to reproduce it, but frequent enough to significantly decrease the crashfree):
Fatal Exception: java.lang.IllegalStateException Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()
androidx.fragment.app.Fragment.getViewLifecycleOwner (Fragment.java:377)
com.mycompany.myapp.common.tools.FragmentViewBindingDelegate.getValue (FragmentViewBindingDelegate.kt:40)
com.mycompany.myapp.feature.cart.home.bulletin.BulletinFragment.<clinit> (BulletinFragment.kt:18)
com.mycompany.myapp.feature.cart.home.bulletin.BulletinFragment.access$getBinding (BulletinFragment.java:15)
com.mycompany.myapp.feature.cart.home.bulletin.BulletinFragment$onViewCreated$2$1$1.emit (BulletinFragment.kt:25)
com.mycompany.myapp.feature.cart.home.bulletin.BulletinFragment$onViewCreated$2$1$1.emit (BulletinFragment.kt:24)
com.mycompany.myapp.domain.usecase.notifications.LiveNotificationsUseCase$getSwitchStateFlow$$inlined$map$1$2.emit (Emitters.kt:227)
com.mycompany.myapp.domain.usecase.notifications.LiveNotificationsUseCase$getSwitchStateFlow$$inlined$map$1$2$1.invokeSuspend (Emitters.kt:12)
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
kotlinx.coroutines.internal.DispatchedContinuation.resumeWith (DispatchedContinuation.kt:205)
kotlin.coroutines.SafeContinuation.resumeWith (SafeContinuationJvm.kt:41)
How can we endup with this crash when
we tie the coroutine with the viewLifecycleOwner lifecycleScope
and the collect is done inside a block where the lifecycleOwner state is STARTED, the lifecycleOwner being the view if I properly understand.
How the view can be null in this case ??? Is it related to the ViewPager2

The application theme is not saved

I have a code that switches themes. But if I restart the application, the standard theme is set. Help me how to make sure that the theme is saved, which was selected last time.
class MainActivity : AppCompatActivity(), KodeinAware, SharedPreferences.OnSharedPreferenceChangeListener {
override val kodein by closestKodein()
private val fusedLocationProviderClient: FusedLocationProviderClient by instance()
private lateinit var binding: ActivityMainBinding
private val locationCallBack = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
super.onLocationResult(p0)
}
}
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
//setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this)
navController = Navigation.findNavController(this, R.id.nav_host_fragment)
bottom_nav.setupWithNavController(navController)
NavigationUI.setupActionBarWithNavController(this,navController)
if (hasLocationPermission()) {
bindLocationManager()
}
else {
requestLocationPermission()
}
//AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == "dark_mode"){
val prefs = sharedPreferences?.getString(key, "1")
when(prefs?.toInt()){
1->{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
2->{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
3->{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_TIME)
}
4->{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
}
}
}
}
}
This my ListPreference
<ListPreference
android:key="dark_mode"
android:title="Темы"
android:defaultValue="1"
app:useSimpleSummaryProvider="true"
android:entries="#array/dark_mode_entries"
android:entryValues="#array/dark_mode_entries_values"/>
Your problem is you only apply the theme in onSharedPreferenceChanged(), which will only be called at the moment when the setting is modified. You should also do this in onCreate so the setting is applied every time the Activity opens. Since you're doing it in two places, you should break it out into a separate function.
I also cleaned your code a bit. Call this function inside onCreate(), and also call it inside onSharedPreferenceChanged() instead of the code you currently have in that function.
private fun applyDarkModeSetting() {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
val settingValue = sharedPreferences.getString("dark_mode", null)?.toIntOrNull() ?: 1
val mode = when (settingValue) {
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_NO
3 -> AppCompatDelegate.MODE_NIGHT_AUTO_TIME
else -> AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
}
AppCompatDelegate.setDefaultNightMode(mode)
}

How to access Application class variables in activity in kotlin android

I used to access application class private variables by using a
public methods in java
How to do the same using kotlin
App.kt
class App : Application() {
private var app: App? = null
private var movieAppComponent: MovieAppComponent? = null
override fun onCreate() {
super.onCreate()
app = this
movieAppComponent = DaggerMovieAppComponent.builder()
.applicationModule(ApplicationModule(this))
.netModule(NetModule(Keys.BASE_URL, this))
.build()
}
fun getApp(): App? {
return app
}
fun getMovieAppComponent(): MovieAppComponent? {
return movieAppComponent
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
App.getApp().getMovieAppComponent().inject(this)
}
}
Error:
App.getApp().getMovieAppComponent().inject(this)
Here getApp() i am getting as unresolved reference
Solution 1:
class App : Application() {
private var movieAppComponent: MovieAppComponent? = null
companion object {
private var app: App? = null
fun getApp(): App? {
return app
}
}
override fun onCreate() {
super.onCreate()
app = this
movieAppComponent = DaggerMovieAppComponent.builder()
.applicationModule(ApplicationModule(this))
.netModule(NetModule(Keys.BASE_URL, this))
.build()
}
fun getMovieAppComponent(): MovieAppComponent? {
return movieAppComponent
}
}
Solution 2:
No need to create such method. You can use type casting in your Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(application as? App)?.getMovieAppComponent()?.inject(this)
}
}

Kotling :: Android :: java.lang.ClassCastException: java.lang.Class cannot be cast to androidx.lifecycle.ViewModel

I am getting an exception in the first line of the code below
viewModel.homeLiveData.observe(this, Observer { list ->
list?.let {
mList.addAll(list)
adapter.notifyDataSetChanged()
}
})
java.lang.ClassCastException: java.lang.Class cannot be cast to androidx.lifecycle.ViewModel
The Whole code is Below
what is wrong with the cast ? is there anything wrong of I am creating my ViewModel?
My BaseActivity
abstract class BaseActivity<V : ViewModel> : DaggerAppCompatActivity(), HasSupportFragmentInjector {
#Inject
lateinit var fragmentAndroidInjector: DispatchingAndroidInjector<Fragment>
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
#LayoutRes
abstract fun layoutRes(): Int
protected lateinit var viewModel : V
protected abstract fun getViewModel() : Class<V>
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == android.R.id.home)
onBackPressed()
return super.onOptionsItemSelected(item)
}
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(layoutRes())
viewModel = ViewModelProviders.of(this, viewModelFactory).get(getViewModel())
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentAndroidInjector
}
then My Activity
class MainActivity : BaseActivity<MainViewModel>() {
override fun layoutRes(): Int = R.layout.activity_main
override fun getViewModel(): Class<MainViewModel> = MainViewModel::class.java
private val mList = mutableListOf<Any>()
private lateinit var adapter: DataAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setSupportActionBar(toolbar)
recyclerView.apply {
layoutManager = GridLayoutManager(applicationContext, 2)
adapter = DataAdapter(context, mList)
}
viewModel.homeLiveData.observe(this, Observer { list ->
list?.let {
mList.addAll(list)
adapter.notifyDataSetChanged()
}
})
viewModel.getHomeItems()
}
and this is my ViewModel
class MainViewModel #Inject constructor() : ViewModel() {
val homeLiveData: MutableLiveData<List<HomeScreenModel>> = MutableLiveData()
fun getHomeItems() {
Handler().post {
val homeModleList = listOf(
HomeScreenModel(R.drawable.ic_launcher_background, MyApplication.instance.getString(R.string.settings))
)
homeLiveData.setValue(homeModleList)
}
}
}
In my opinion, your viewModel property, which you try to access in viewModel.homeLiveData is shadowed by getViewModel() abstract function that you declare in BaseActivity. This is because Kotlin thinks that getXyZ() is a getter for the field xyZ and thus when you access viewModel, the compiler thinks you want to call getViewModel, which is of type Class<V>. I suggest renaming either the function or the property and it should work then.
Check your viewModel factory if you implemented it correctly

Boolean arguments issue when creating Settings activity

After creating an activity for a Settings page I noticed that, mCurrentValue !== value in if (mCurrentValue !== value) returned a warning:
Identity equality for arguments of types Boolean? and Boolean can be unstable because of implicit boxing
I tried resolving this warning by adding a ? next to Boolean in override fun onXchange(value:Boolean) {, but then the following error returned:
'onXchange' overrides nothing
Any ideas on how to resolve this issue?
Activity class
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)
}
}
}
Fragment class
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
}
}
So first I can explain the issue it describes. Let's propose a very contrived scenario:
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)
}
}
This test will actually fail, because the instances of Boolean are not the same. In the Java code, we initialized a new instance of Boolean (rather than the statically defined Boolean.TRUE and Boolean.FALSE instances that you'll get when a primitive is auto-boxed to a java.lang.Boolean). So to avoid a potential unexpected result, it is recommending that you don't compare these types by reference.
The simplest fix would be to just change your equality test to != instead of !==. This would perform identity equality testing rather than reference equality testing, and will handle a null value on either side appropriately. This is what you want 99% of the time anyway.
Secondly, you can also just declare mCurrentValue as a non-null type, and give it a default value, if you don't need to handle a null value in a specific way. Just declare it as:
private var mCurrentValue: Boolean = false // false is the default here

Categories

Resources