Kotlin for Android Developers
Accessing Shared Preferences
Download 1.04 Mb. Pdf ko'rish
|
Kotlin for Android Developers Learn Kotlin the Easy Way While Developing an Android App ( PDFDrive )
26.2 Accessing Shared Preferences
You probably know what Android Shared Preferences²⁸ are. They consist of a set of keys and values that can be easily saved and restored by using the Android framework. These preferences ²⁸ http://developer.android.com/training/basics/data-storage/shared-preferences.html 26 Settings Screen 128 are integrated with some parts of the SDK to make some tasks easier. Besides, since Android 6.0 (Marshmallow), shared preferences can be automatically cloud-saved, so when a user restores the App in a new device, these preferences are restored too. Thanks to the use of property delegation, we can deal with preferences in a very easy way. We can create a delegate that queries the preference when get is called and saves it when we call to set . As we want to save the zip code, which is a long value, let’s create a delegate for Long properties. In DelegatesExtensions.kt , implement a new LongPreference class: 1 class LongPreference(val context: Context, val name: String, val default: Long) 2 : ReadWriteProperty 3 4 val prefs by lazy { 5 context.getSharedPreferences("default", Context.MODE_PRIVATE) 6 } 7 8 override fun getValue(thisRef: Any?, property: KProperty<*>): Long { 9 return prefs.getLong(name, default) 10 } 11 12 override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { 13 prefs.edit().putLong(name, value).apply() 14 } 15 } First, we create a lazy access to preferences. That way, if we don’t use the property, this delegate will never request the SharedPreferences object. When get is called, its implementation will use the preferences instance to retrieve a long property with the name that was specified in the delegate declaration, and defaulting to the default value if the property is not found. When a value is set, a preferences editor is requested and the value will be saved using the name of the property. We can then define the new delegate in the DelegatesExt object, so that it’s easier to access when required: 1 object DelegatesExt { 2 .... 3 fun longPreference(context: Context, name: String, default: Long) = 4 LongPreference(context, name, default) 5 } In SettingsActivity , a property to deal with zip code preference can now be defined. I’m also creating a couple of constants which keep the name and default value of the property. That way they can be used in other sections of the App. 26 Settings Screen 129 1 companion object { 2 val ZIP_CODE = "zipCode" 3 val DEFAULT_ZIP = 94043L 4 } 5 6 var zipCode: Long by DelegatesExt.longPreference(this, ZIP_CODE, DEFAULT_ZIP) Now it’s really easy to work with this preference. In onCreate , we get the value of the property and assign it to the EditText : 1 override fun onCreate(savedInstanceState: Bundle?) { 2 ... 3 cityCode.setText(zipCode.toString()) 4 } We can’t use the auto-generated property text because EditText returns an Editable in getText , so the property is defaulted to that value. If we try to assign a String , the compiler will complain. Using setText() will be enough. Now we have everything we need to implement onBackPressed . Here, the new value of the property is saved: 1 override fun onBackPressed() { 2 super.onBackPressed() 3 zipCode = cityCode.text.toString().toLong() 4 } The MainActivity requires some little changes. First, it also needs a zipCode property. 1 val zipCode: Long by DelegatesExt.longPreference(this, SettingsActivity.ZIP_CODE, 2 SettingsActivity.DEFAULT_ZIP) And then, I’m moving the forecast load to onResume so that every time the activity is resumed, it refreshes the data, just in case the zip code changed. Of course, there are more efficient ways to do this, by checking whether the zip code really changed before requesting the forecast again, for instance. But I want to keep this example simple, and the requested info is already saved in a local database, so this solution is not that bad: 26 Settings Screen 130 1 override fun onResume() { 2 super.onResume() 3 loadForecast() 4 } 5 6 private fun loadForecast() = async { 7 val result = RequestForecastCommand(zipCode).execute() 8 uiThread { 9 val adapter = ForecastListAdapter(result) { 10 startActivity 11 DetailActivity.CITY_NAME to result.city) 12 } 13 forecastList.adapter = adapter 14 toolbarTitle = "${result.city} (${result.country})" 15 } 16 } The RequestForecastCommand is now using the zipCode property instead of the previous fixed value. There’s just one more thing we must do: start the settings activity when the user clicks on the overflow action. In ToolbarManager , the initToolbar function requires a small change: 1 when (it.itemId) { 2 R.id.action_settings -> toolbar.ctx.startActivity 3 else -> App.instance.toast("Unknown option") 4 } Download 1.04 Mb. Do'stlaringiz bilan baham: |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling