Giter Club home page Giter Club logo

kotpref's People

Contributors

ashok-varma avatar beigirad avatar chibatching avatar davidgarciaanton avatar janbina avatar ligi avatar miha-x64 avatar plackemacher avatar s0nerik avatar themaxcoder avatar tunous avatar wrozwad avatar yoavst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotpref's Issues

Rxjava + Kotpref

It is possible to use rxjva to be notified when one preference change?

How to mock Kotpref in tests

I've tried to test method with Kotpref line UserCredentialsPref.username but I've always got same error java.lang.IllegalStateException: Kotpref has not been initialized.

StringSetPref isn't aware of changes made by PreferenceFragment

Unlike all the Prefs that extend AbstractPref, such as StringPref or IntPref: StringSetPref has a memory cache of the value that it represents, instead of fetching from the SharedPreferences when requested.

So when implementing a xml preference, as seen in #47. The value of the StringSetPref isn't updated when a user makes changes via a PreferenceFragment.

A work-around is to perform a beginBulkEdit() and then cancelBulkEdit() in sequence before reading these values.

The problems lies in the getValue method of the StringSetPref class, as seen here:

    override operator fun getValue(thisRef: KotprefModel, property: KProperty<*>): MutableSet<String> {
        if (stringSet == null || lastUpdate < thisRef.kotprefTransactionStartTime) {
            val prefSet = thisRef.kotprefPreference.getStringSet(key ?: property.name, null)
                ?.let { HashSet(it) }
            stringSet = PrefMutableSet(
                thisRef,
                prefSet ?: default.invoke().toMutableSet(),
                key ?: property.name
            )
            lastUpdate = SystemClock.uptimeMillis()
        }
        return stringSet!!
    }

One way of fixing it would be to replace the content of the stringSet: MutableSet<String>? when reading the value, and removing the if condition. Something like this:

    override operator fun getValue(thisRef: KotprefModel, property: KProperty<*>): MutableSet<String> {
        val prefSet = thisRef.kotprefPreference.getStringSet(key ?: property.name, null)
                ?.let { HashSet(it) }

        stringSet = stringSet?.apply {
            //TODO Update its content with prefSet without triggering preference file editing
        } ?: PrefMutableSet(
                thisRef,
                prefSet ?: default.invoke().toMutableSet(),
                key ?: property.name)
        return stringSet!!
    }

Kotpref unitTesting without android context

We have a lot of code that depends in kotpref.

And we have also many unitTests.
Majority of them do not use android emulator or context to be as fast as possible.
As is, we can not instantiate kotpref, and so we need to put if's in all place to only see preference's if we are not unit testing so that will not break.

Could kotpref have an boolean option to set it for unit testing = true.
In that option, it only return the setted preference value, but not save it to android preferences?
That would be great!

Support for versioning

As of now, there is no support for versioning of KotprefModel. This is useful in some cases when someone wants to remove a key on version update, or clear the complete model itself.

This could be provided by having a version number in KotprefModel and calling an abstract function onVersionUpdate whenever the version number is increased.

Remove entry

It's not yet possible to remove an entry from the shared preferences. Would be nice if this works.

StringSetPref iterator

Hello.
I've noticed that all mutating operations on a set are being applied immediately, e. g.

val result = set.add(element)
kotprefModel.kotprefPreference.edit().putStringSet(key, set).apply()
return result

but iterator() funciton just returns undecorated set.iterator(), and it's easy to call remove() on it without triggering SharedPreferences update.
Am I right? Will this be fixed? Do you need help with it?

StringSetPref isn't aware of changes made by PreferenceFragment

Unlike all the Prefs that extend AbstractPref, such as StringPref or IntPref: StringSetPref has a memory cache of the value that it represents, instead of fetching from the SharedPreferences when requested.

So when implementing a xml preference, as seen in #47. The value of the StringSetPref isn't updated when a user makes changes via a PreferenceFragment.

A work-around is to perform a beginBulkEdit() and then cancelBulkEdit() in sequence before reading these values.

The problems lies in the getValue method of the StringSetPref class, as seen here:

    override operator fun getValue(thisRef: KotprefModel, property: KProperty<*>): MutableSet<String> {
        if (stringSet == null || lastUpdate < thisRef.kotprefTransactionStartTime) {
            val prefSet = thisRef.kotprefPreference.getStringSet(key ?: property.name, null)
                ?.let { HashSet(it) }
            stringSet = PrefMutableSet(
                thisRef,
                prefSet ?: default.invoke().toMutableSet(),
                key ?: property.name
            )
            lastUpdate = SystemClock.uptimeMillis()
        }
        return stringSet!!
    }

One way of fixing it would be to replace the content of the stringSet: MutableSet<String>? when reading the value, and removing the if condition. Something like this:

    override operator fun getValue(thisRef: KotprefModel, property: KProperty<*>): MutableSet<String> {
        val prefSet = thisRef.kotprefPreference.getStringSet(key ?: property.name, null)
                ?.let { HashSet(it) }

        stringSet = stringSet?.apply {
            //TODO Update its content with prefSet without triggering preference file editing
        } ?: PrefMutableSet(
                thisRef,
                prefSet ?: default.invoke().toMutableSet(),
                key ?: property.name)
        return stringSet!!
    }

Kotpref 2

  • Simplify API name
  • Split auto-initialization module
  • Split basic module and advance usage module like enum support

java.lang.NoClassDefFoundError in Android KitKat (4.4)

Hi, i am getting this error
java.lang.NoClassDefFoundError: at com.chibatching.kotpref.initializer.KotprefInitProvider.onCreate (KotprefInitProvider.kt:20) at android.content.ContentProvider.attachInfo (ContentProvider.java:1638) at android.content.ContentProvider.attachInfo (ContentProvider.java:1609) at android.app.ActivityThread.installProvider (ActivityThread.java:5008) at android.app.ActivityThread.installContentProviders (ActivityThread.java:4582) at android.app.ActivityThread.handleBindApplication (ActivityThread.java:4522) at android.app.ActivityThread.access$1500 (ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1381) at android.os.Handler.dispatchMessage (Handler.java:110) at android.os.Looper.loop (Looper.java:193) at android.app.ActivityThread.main (ActivityThread.java:5292) at java.lang.reflect.Method.invokeNative (Native Method) at java.lang.reflect.Method.invoke (Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:824) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:640) at dalvik.system.NativeStart.main (Native Method)
on phones with Android SDK 19 (KitKat 4.4). I am using com.chibatching.kotpref:initializer:2.5.0

Make clear() method open

As stated in the title.

I'm trying to perform a verification/assertion on the clear() method of a KotprefModel, and right now I have no way of doing so.

I don't think there are no drawbacks in opening the method, as I couldn't find any internal usage of the method.

Thanks again for the great library and support you are giving =)

Double ?

Hi and thanks for this beautifull library :)

Is it possible to add Double type ?

thanks

How can i map to xml prefs

I have an XML preference

 <ListPreference
            android:id="@+id/pref_music_repeat"
            android:defaultValue="0"
            android:entries="@array/Replay_arrays"
            android:entryValues="@array/array_repeat_value"
            android:icon="@drawable/ic_pref_time"
            android:key="key_music_repeat"
            android:summary="%s"
            android:title="Repeat Count" />

How can i use this in Kotpref

Add test for gson type

In #88, gson support module uses gson TypeToken to support generics type.
We need some test for it, List or Map etc...

Expose a way to add a listener to preferences

Adding a listener so something can be notified when a preference is changed seems like common behavior, but I can't find a way to do so easily.

The SharedPreferences instance is internal to KotPrefModel, so using OnSharedPreferenceChangeListener requires actually getting the sharedPrefs object based on the class name, which you'd need to calculate yourself or hardcode.

Exposing the sharedPreferences object in KotprefModel would be an easy solution to this. Another would be writing your own wrapper for listeners.

Adding parcelable support.

I might be missing something but as far as i can tell there is no way to currently add a parcelable object.

Is it supported currently and if not are there any plans to add support for it?

commit/apply as an option

Thankyou for such a wonderful library. Using it in many of my projects.

in many cases app might need commit for some properties.

commit/apply doesn't much depend on scenario, those rather depend on property.
we can use blockingCommit but adding blockingCommit every time we access that property is difficult.

i am added default commit support in my project. i can create a pull request, if you are ok with that. If there are any pitfalls please let me know.

This is how i did it.

  1. all prefs will have commit in constructor, based on that we will do apply/commit
    stringPref and extension fun sample snippets
internal class StringPref(val default: String, val key: String?, private val commitByDefault: Boolean)
    override fun setToPreference(property: KProperty<*>, value: String, preference: SharedPreferences) {
        preference.edit().putString(key ?: property.name, value).execute(commitByDefault)
    }

fun  SharedPreferences.Editor.execute(commit : Boolean) {
    if(commit)
        commit()
    else
        apply()
}
  1. changes to KotprefModel
protected open val commitAllPropertiesByDefault: Boolean = false

protected fun stringPref(default: String = "", key: String? = null, commitByDefault : Boolean = commitAllPropertiesByDefault)
            : ReadWriteProperty<KotprefModel, String> = StringPref(default, key, commitByDefault)

I have done these for json, enum projects as well
Let me know if there are any changes i need to do.

Commit changes

Hello. Thank you for a great library!

I need a way to commit() some changes instead of apply()ing them to save some crash information and exit immediately in my uncaught exception handler.

Here is my implementation: #22

Moshi support

Great library!

Could you please create an artifact also for moshi support? (https://github.com/square/moshi)

I believe it would be easy to add this starting from the gson-support code. Moshi is very similar to gson.

Thanks!

Nullable preferences

I use your library and it seems a proper way to work with preferences from Kotlin.

However I found one disadvantage: it is not possible to put the null value to a preference (see example bellow). In origin Android preference model I can do it through the Editor interface. In this case, when I read this property, I retrieve null or default value (if specified).

public object DevicePreference : KotprefModel() {
var key: String? by stringPrefVar(default = "")
}

In current case I should to write uncomfortable setting code:

string: String? = ""
DevicePreference.key = string ?: ""

I think that you should allow to set the null value to a preference. In this case it less comfortable to read value (need to add "!!" symbols) but users should chose preferable way by yourself.

Suggestion - module for preference screen

How about an extra module to create a preference screen for a KotprefModel? Would be a very useful addition.

I've done smoething like this for my own KotprefModule, could share the code with you so that you could derive a generic solution for this. Let me know if you're interested

What is the bast way to handle DropDownPreference integer values

I have a DropDownPreference with integer values. Android needs string-array for values to be used and that crates an issue where I have to define preference model member as var myPref: String by stringPref.

Is there a correct way of of accessing this preference apart from converting it to Int in my code?

Support list and other models with gsonPref

It will be nice to be available to use

var availableOfferList: List<OfferItem> by gsonPref(Collections.emptyList())

or

var offerDetails: Map<Long, OfferDetails> by gsonPref(Collections.emptyMap())

dynamic preferences

Maybe adding something like that to KotprefModel:

publlic fun set(field: String, supportedType: SupportedTypeComesHere) {
  ...
}

and a get for each type.

How to use Map with gsonPref

class ProductLocal(context: Context) : KotprefModel() {
    var productMap by gsonPref(HashMap<String,String>())
    var productContentsMap by gsonPref(ConcurrentHashMap<String,String>())

}

I have tried both and none of them works. Am I missing anything here?

productLocal.productContentsMap.putAll ()

java.lang.NoClassDefFoundError: com.chibatching.kotpref.KotprefPreferences$KotprefEditor$apply$1

After updating to kotpref 2.1.0 and Kotlin 1.1.1 my UI-Tests fail with:

E/AndroidRuntime( 7659): Process: org.ligi.gobandroid_hd, PID: 7659
E/AndroidRuntime( 7659): java.lang.NoClassDefFoundError: com.chibatching.kotpref.KotprefPreferences$KotprefEditor$apply$1
E/AndroidRuntime( 7659): 	at com.chibatching.kotpref.KotprefPreferences$KotprefEditor.apply(KotprefPreferences.kt:21)
E/AndroidRuntime( 7659): 	at com.chibatching.kotpref.KotprefModel.commitBulkEdit(KotprefModel.kt:199)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.refresh_ui(GameSetupFragment.kt:151)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.onProgressChanged(GameSetupFragment.kt:80)
E/AndroidRuntime( 7659): 	at android.widget.SeekBar.onProgressRefresh(SeekBar.java:91)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:655)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.refreshProgress(ProgressBar.java:667)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.setProgress(ProgressBar.java:714)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.setProgress(ProgressBar.java:695)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.refresh_ui(GameSetupFragment.kt:109)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.onProgressChanged(GameSetupFragment.kt:80)
E/AndroidRuntime( 7659): 	at android.widget.SeekBar.onProgressRefresh(SeekBar.java:91)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:655)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.refreshProgress(ProgressBar.java:667)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.setProgress(ProgressBar.java:714)
E/AndroidRuntime( 7659): 	at android.widget.ProgressBar.setProgress(ProgressBar.java:695)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.refresh_ui(GameSetupFragment.kt:105)
E/AndroidRuntime( 7659): 	at org.ligi.gobandroid_hd.ui.game_setup.GameSetupFragment.onStart(GameSetupFragment.kt:66)
E/AndroidRuntime( 7659): 	at android.support.v4.app.Fragment.performStart(Fragment.java:2218)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1340)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:2907)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentController.dispatchStart(FragmentController.java:212)
E/AndroidRuntime( 7659): 	at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:613)
E/AndroidRuntime( 7659): 	at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
E/AndroidRuntime( 7659): 	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
E/AndroidRuntime( 7659): 	at android.app.Activity.performStart(Activity.java:5241)
E/AndroidRuntime( 7659): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2168)
E/AndroidRuntime( 7659): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
E/AndroidRuntime( 7659): 	at android.app.ActivityThread.access$800(ActivityThread.java:135)
E/AndroidRuntime( 7659): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
E/AndroidRuntime( 7659): 	at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 7659): 	at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime( 7659): 	at android.app.ActivityThread.main(ActivityThread.java:5017)
E/AndroidRuntime( 7659): 	at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 7659): 	at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 7659): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/AndroidRuntime( 7659): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/AndroidRuntime( 7659): 	at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager( 1549): Force-killing crashed app org.ligi.gobandroid_hd at watcher's request

will have to digg a bit deeper - but dropping this here now as I guess the root is in kotpref and you might see whats wrong in a glance without digging.

KotprefModel.asLiveData has some issue

gradle

 implementation 'com.chibatching.kotpref:kotpref:2.9.1'
 implementation 'androidx.lifecycle:lifecycle-livedata:2.0.0'
 implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.41"

my user data is

object User :KotprefModel(){
    var username by stringPref()
    var token by stringPref()
    var uid by intPref()
     var isLogin by booleanPref()
    val isLogined = User.asLiveData(User::isLogin)//highlight code

}

my fragment

class FragmentTwo : BaseFragment() {

    companion object {
        fun newInstance() = FragmentTwo()
    }

    private  val  viewModel by lazy { ViewModelProviders.of(requireActivity()).get(FragmentTwoViewModel::class.java) }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_two_fragment, container, false)
        val bind = DataBindingUtil.bind<FragmentTwoFragmentBindingImpl>(view)
        bind?.lifecycleOwner = this
        bind?.twoVm = viewModel


        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        // TODO: Use the ViewModel
        viewModel.isStart.observe(this, Observer {
            startActivity(Intent(context,it.first))
        })
       //highlight code
        User.isLogined.observe(this, Observer {
            Log.d(javaClass.name,"asLiveData(User::isLogin) $it")
        })

    }

}

when i wanna change isLogin in this method

                User.isLogin = true

fragment observe is not called

when i change extend code

KotprefModel.asLiveData
remove this@asLiveData.preferences.unregisterOnSharedPreferenceChangeListener(this)

the observe is working.


I think there is some issue in KotprefModel.asLiveData

Enum support?

Hey there! Was just browsing through possible libraries to use to simplify interactions with SharedPreferences while using Kotlin and found yours.

Are there any plans on supporting enum storage while allowing customization between storage as a string or an integer from an ordinal? If you already have something in the works, that's great. If not, I could gladly contribute support for it to this library.

Persisting custom objects

Hello again :)
What about supporting pref values, which could be presisted into String by custom converter?

object AppState { // client code
    val user by customPref<User?>(default = null, converter = UserConverter)
}

interface PrefConverter<T> { // library code
    fun fromPref(str: String): T
    fun toPref(t: T): String
}

object UserConverter : PrefConverter<User> { // client code
    private val gson = Gson()
    override fun fromPref(str: String) = gson.fromJson(str, User::class.java)
    override fun toPref(t: T) = gson.toJson(t)
}

Many ORMs (Hibernate, GreenDAO, ORMLite, ObjectBox, etc) do this for object's fields, so we can borrow some architectural solutions from them.

PreferencesOpener version

Pleeease release a new version to support:
androidx.security.crypto.EncryptedSharedPreferences

Let the app decide using PreferencesOpener

StringSetPref not being saved immediately

On button press I add some string to set and then print all

UserData.enabledPeers.add(userId);
UserData.enabledPeers.forEach {
    Log.e("Enabled peers", it)
}

New string is here.
Then I kill process (swipe out from recents), launch it and print again.
New string isn't here anymore =(

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.