Skip to content

Commit 4158260

Browse files
committed
sharedpreferences post added and some updated
1 parent 8eb2713 commit 4158260

11 files changed

+174
-10
lines changed

_drafts/2019-05-27-rxandroid.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
layout: post
3-
title: "RxAndroid"
3+
title: "RxJava"
44
date: 2019-05-27
55
categories: ["Biblioteki"]
6-
image: libraries/rxandroid
7-
github: libraries/tree/master/rxandroid
6+
image: libraries/rxjava
7+
github: libraries/tree/master/rxjava
88
description: "Biblioteki"
9-
version: RxAndroid 2.1, RxJava 2.2
9+
version: RxJava 2.2, RxAndroid 2.1
1010
keywords: "reaktywne, reactive, rxandroid, rxjava, reactivex, obserwator, obserwowany, observer, observable, schedulers, operator, disposable, subscribe, async, thread, java, android, programowanie, programming"
1111
---
1212

@@ -94,7 +94,7 @@ private List<String> prepareData() {
9494
{% endhighlight %}
9595

9696
## Harmonogramy
97-
Wprowadzone w module `RxAndroid` harmonogramy decydują o tym na jakim wątku obiekt obserwowany będzie wykonywał zadanie oraz na jakim wątku obiekt obserwatora będzie odbierał i przetwarzał wyemitowane dane. Najpopularniejszymi harmonogrami są: `AndroidSchedulers.mainThread` - odpowiada za główny wątek aplikacji, `Schedulers.io` - wykorzystywany w nie wymagających operacjach i `Schedulers.computation` - przeznaczony do przetwarzania intensywnych zadań. Wyróżnia się także `Schedulers.newThread`, `Schedulers.single`, `Schedulers.immediate`, `Schedulers.trampoline`, `Schedulers.from`, które różnią się synchronicznością, kolejnością, czasem rozpoczęcia i ilością przetwarzanych zadań. Przypisanie harmonogramu dokonywane jest na obiekcie obserwowanym za pomocą metod `subscribeOn` i `observeOn`.
97+
Harmonogramy decydują o tym na jakim wątku obiekt obserwowany będzie wykonywał zadanie oraz na jakim wątku obiekt obserwatora będzie odbierał i przetwarzał wyemitowane dane. Najpopularniejszymi harmonogrami są: `AndroidSchedulers.mainThread` - odpowiada za główny wątek aplikacji (wprowadzony w module `RxAndroid`), `Schedulers.io` - wykorzystywany w nie wymagających operacjach i `Schedulers.computation` - przeznaczony do przetwarzania intensywnych zadań. Wyróżnia się także `Schedulers.newThread`, `Schedulers.single`, `Schedulers.immediate`, `Schedulers.trampoline`, `Schedulers.from`, które różnią się synchronicznością, kolejnością, czasem rozpoczęcia i ilością przetwarzanych zadań. Przypisanie harmonogramu dokonywane jest na obiekcie obserwowanym za pomocą metod `subscribeOn` i `observeOn`.
9898

9999
{% highlight java %}
100100
private void startWorkAndSubscribe() {

_drafts/2019-07-08-service.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ keywords: "service, thread, task, foreground, background, bound, start, bind, on
1111

1212
## Wstęp
1313
`Service` jest usługą dziąłającą w tle na głównym wątku aplikacji. Nie posiada interfejsu użytkownika i jest niezależny względem cyklu życia aktywności (`Activity`). Komponenty mogą związać się do serwisu w celu interakacji z nim. Wykorzystywany przede wszystkim do natychmiastowego wykonywania długich, powtarzalnych lub ciągłych zadań w tle implementowanych na wątku roboczym (np. pobieranie, przetwarzanie danych, odtwarzanie muzyki). Może zostać uruchomiony przez różne komponenty oraz przez inne aplikacje. Jest zdolny do kontynuowania pracy w tle nawet po wyjściu z aplikacji. Może rozpocząć działanie zarówno poprzez wystartowanie jak i podpięcie. Wyróżnia się trzy tryby działania serwisu: `background`, `foreground` i `bound`.
14+
1415
## Ograniczenia
1516
Ze względu na wykonywanie pracy całego serwisu na wątku głównym należy zaimplementować kosztowne zadania usługi w oparciu o wątki robocze lub jako alternatywę rozważyć wykorzystanie `IntentService`. W zależności od wybranego trybu działania serwisu trzeba uwzględnić także konieczność dostarczenia mechanizmu odpowiedzi zwrotnej do klienta oraz restrykcję systemu dla procesów działających w tle. Jeśli wykonywanie zadania ma sens tylko w ramach aktywnego danego ekranu czy też powiązane jest z cyklem życia komponentu należy zrezygnować z wykorzystania `Service` i użyć innych mechanizmów takich jak np. `AsyncTask` czy `HandlerThread`.
1617

_drafts/2019-07-15-intentservice.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ class CustomIntentService : IntentService("name") {
2929
//they are automatically invoked by IntentService
3030
}
3131

32-
class MainActivity : AppCompatActivity() {
32+
class CustomActivity : AppCompatActivity() {
3333

3434
override fun onCreate(savedInstanceState: Bundle?) {
3535
super.onCreate(savedInstanceState)
36-
setContentView(R.layout.activity_main)
36+
setContentView(R.layout.activity_custom)
3737
button.setOnClickListener { startIntentService() }
3838
}
3939

@@ -70,13 +70,13 @@ class IntentServiceCommunication : IntentService("name") {
7070
}
7171
}
7272

73-
class MainActivity : AppCompatActivity() {
73+
class CommunicationActivity : AppCompatActivity() {
7474

7575
private val receiver = CustomBroadcastReceiver()
7676

7777
override fun onCreate(savedInstanceState: Bundle?) {
7878
super.onCreate(savedInstanceState)
79-
setContentView(R.layout.activity_main)
79+
setContentView(R.layout.activity_communication)
8080
button.setOnClickListener { startIntentService() }
8181

8282
registerReceiver(receiver, IntentFilter("FILTER_ACTION"))

_drafts/2019-07-22-workmanager.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class FinalWorker(context: Context, params: WorkerParameters) : Worker(context,
169169
`JobScheduler` pozwala na planowanie zadań w tle gwarantując ich ukończenie w nieokreślonej przyszłości. Wykonanie zadania jest uzależnione od warunków stanu systemu. Może się zdarzyć, że rozpoczęcie pracy będzie natychmiastowe lub pozostanie w oczekiwaniu na korzystny stan systemu umożliwiający podjęcie działania zgodnie z wymaganiami wstępnymi. Optymalizuje użycie baterii i pamięci w stosunku do innych kosztownych rozwiązań realizacji pracy w tle takich jak np. `Service`, `AlarmManager` czy `BroadcastReceiver`. Usługa `JobScheduler` jest jednak dostępna od wersji systemu `Android L`. Alernatywnym rozwiązaniem może być wykorzystanie `FirebaseJobDispatcher` (działa także poniżej `Android L`). Obie usługi działają w oparciu o `JobService`, którego zadaniem jest obsługa zdarzeń rozpoczęcia i zatrzymania pracy. Warunki wstępne deklarowane są w obiektach `JobInfo` lub `Job`, a zaplanowanie zadania odbywa się przy pomocy metody `schedule`.
170170

171171
{% highlight kotlin %}
172-
class JobScheduler : AppCompatActivity() {
172+
class JobSchedulerActivity : AppCompatActivity() {
173173

174174
lateinit var jobScheduler: JobScheduler //works min for API 21
175175
lateinit var jobDispatcher: FirebaseJobDispatcher //alernative for lower API
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
---
2+
layout: post
3+
title: "SharedPreferences"
4+
date: 2019-08-05
5+
categories: ["Przechowywanie"]
6+
image: store/sharedpreferences
7+
github: store/tree/master/sharedpreferences
8+
description: "Przechowywanie danych"
9+
keywords: "store, data, datastore, sharedpreferences, preferences, key, value, primitive, settings, get, put, editor, android, programowanie, programming"
10+
---
11+
12+
## Charakterystyka
13+
`SharedPreferences` umożliwiają przechowywanie i zarządzanie prostymi danymi prymitywów tj.: wartości logiczne, liczby całkowite i zmiennoprzecinkowe oraz teksty w postaci pary `klucz - wartość`. Dane przechowywane są na urządzeniu w plików `xml` niezależnie od cyklu życia aplikacji. Istnieją tak długo dopóki nie zostaną usunięte przez kod programu lub wyczyszczone ręcznie przez użytkownika z danych aplikacji. Aplikacja może posiadać wiele instancji `SharedPreferences`, które najczęściej są prywatne lecz mogą być także publiczne dla innych aplikacji.
14+
15+
## Przeznaczenie
16+
Nazwa `SharedPreferences` może sugerować przeznaczenie do przechowywania informacji nt ustawień użytkownika, co jest po części prawdą. Jednakże wszystkie informacje, które można sprowadzić do postaci klucz - wartość nadają się do umieszczenia w `SharedPreferences`. Mogą więc to być ustawienia czy preferencje użytkownika, ale równie dobrze także inne dane stanu aplikacji (np. najlepszy wynik) czy dane autoryzacyjne. Pomimo, że wiele informacji może być technicznie zapisanych w `SharedPreferences` (np. konwersja do `String`) to nie wszystkie powinny się tam znaleźć. Umieszczając wartości należy kierować się zasadą prostych, pojedynczych informacji (nie kolekcji). W pozostałych przypadkach warto rozważyć alternatywy w postaci m.in. plików i bazy danych.
17+
18+
## Implementacja
19+
Aby uzyskać referencję do wskazanego pliku `SharedPreferences` należy wywołać metodę `getSharedPreferences` lub `getPreferences`. Czytanie wartości odbywa się za pomocą metod get danego typu, natomiast zapisywanie wartości przebiega jako transakcja na obiekcie `SharedPreferences.Editor`.
20+
21+
{% highlight kotlin %}
22+
class MainActivity : AppCompatActivity() {
23+
24+
override fun onCreate(savedInstanceState: Bundle?) {
25+
super.onCreate(savedInstanceState)
26+
}
27+
28+
fun getSharedPreferences(name : String) : SharedPreferences {
29+
//must be called on Context
30+
return getSharedPreferences(name, Context.MODE_PRIVATE) //pass public to allow access outside app
31+
}
32+
33+
fun getSharedPreferencesForActivity() : SharedPreferences {
34+
//SharedPreferences file only for this activity
35+
return getPreferences(Context.MODE_PRIVATE)
36+
}
37+
38+
fun write(key : String, value : Int) {
39+
val sharedPref = getSharedPreferences("pl.androidcode.app.FILE_KEY")
40+
val editor = sharedPref.edit()
41+
42+
//do some transactions
43+
editor.putInt(key, value) //or use another method to put different types
44+
editor.commit() //to save immediately or apply to save in background
45+
}
46+
47+
fun read(key : String) : Int {
48+
val sharedPref = getSharedPreferences("pl.androidcode.app.FILE_KEY")
49+
val default = 0
50+
return sharedPref.getInt(key, default)
51+
}
52+
}
53+
{% endhighlight %}
54+
55+
## Preference
56+
W przypadku standardowych ustawień aplikacji edytowanych przez interfejs graficzny dobrym pomysłem mogłoby być wykorzystanie biblioteki `Preference`, która ułatwia pracę z `SharedPreferences` poprzez dostarczenie kontrolek widoku dla kluczy ustawień. W tym celu należy stworzyć Fragment rozszerzający `PreferenceFragmentCompat` i w metodzie `onCreatePreferences` przekazać plik `xml` z preferencjami. Wprowadzane zmiany dotyczą globalnych domyślnych ustawień możliwych do uzyskania przez wywołanie `getDefaultSharedPreferences`.
57+
58+
{% highlight kotlin %}
59+
class SettingsActivity : AppCompatActivity() {
60+
61+
override fun onCreate(savedInstanceState: Bundle?) {
62+
super.onCreate(savedInstanceState)
63+
setContentView(R.layout.activity_settings)
64+
65+
//add Preference Fragment
66+
supportFragmentManager
67+
.beginTransaction()
68+
.replace(R.id.container, SettingsFragment())
69+
.commit()
70+
}
71+
72+
//read some pref when needed, use getDefaultSharedPreferences
73+
fun readPref() : Boolean {
74+
val sharedPref = getDefaultSharedPreferences(this)
75+
return sharedPref.getBoolean("pref2", false)
76+
}
77+
}
78+
79+
class SettingsFragment : PreferenceFragmentCompat() {
80+
81+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
82+
setPreferencesFromResource(R.xml.preferences, rootKey)
83+
}
84+
85+
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
86+
return when (preference?.key) {
87+
"pref2" -> {
88+
//do something when pref has changed if needed
89+
true
90+
}
91+
else -> {
92+
super.onPreferenceTreeClick(preference)
93+
}
94+
}
95+
}
96+
97+
//implement more methods to react for interactions
98+
}
99+
{% endhighlight %}
100+
101+
{% highlight kotlin %}
102+
<!-- PreferenceScreen must be parent -->
103+
<androidx.preference.PreferenceScreen
104+
xmlns:app="http://schemas.android.com/apk/res-auto">
105+
106+
<Preference
107+
app:key="pref1"
108+
app:title="Some title"
109+
app:summary="More details"/>
110+
111+
<SwitchPreferenceCompat
112+
app:key="pref2"
113+
app:title="Some message"
114+
app:summary="More details"/>
115+
116+
<!-- use more preferences from Preference class and subclasses -->
117+
118+
</androidx.preference.PreferenceScreen>
119+
{% endhighlight %}
120+
121+
## DataStore
122+
Biblioteka `Preference` domyślnie zarząda danymi wykorzystując implementację `SharedPreferences`. Nierzadko jednak taka realizacja zapisu i odczytu danych może nie być wystarczająca ponieważ może np. zachodzić potrzeba dodatkowego zapisu danych w chmurze ze względu na synchronizację preferencji między urządzeniami. W takiej sytuacji z pomocą przychodzi `PreferenceDataStore` dostępny od wersji systemu `Android O`.
123+
124+
{% highlight kotlin %}
125+
//use custom PreferenceDataStore inside onCretePreferences
126+
class DataStoreFragment : PreferenceFragmentCompat() {
127+
128+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
129+
setPreferencesFromResource(R.xml.preferences, rootKey)
130+
131+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
132+
133+
//enable data store only for specific preference
134+
val preference = findPreference("pref2")
135+
preference.preferenceDataStore = DataStore()
136+
137+
//ore enable for entire hierarchy
138+
preferenceManager.preferenceDataStore = DataStore()
139+
}
140+
}
141+
}
142+
143+
//override only used operations
144+
@RequiresApi(Build.VERSION_CODES.O)
145+
class DataStore : PreferenceDataStore {
146+
147+
//make sure to provide proper non blocking threading during extra work
148+
149+
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
150+
//try to get pref from remote
151+
//if failed or doesn't exists then try to get from local
152+
return super.getBoolean(key, defValue)
153+
//log operation
154+
}
155+
156+
override fun putBoolean(key: String?, value: Boolean) {
157+
//try to put pref to remote
158+
//save also in local
159+
super.putBoolean(key, value)
160+
//log operation
161+
}
162+
}
163+
{% endhighlight %}
File renamed without changes.
File renamed without changes.
584 KB
Loading
21.7 KB
Loading

0 commit comments

Comments
 (0)