Skip to content

Commit 649f1ff

Browse files
committed
feat: extend AString from Parcelable
1 parent 3abe911 commit 649f1ff

23 files changed

+261
-40
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
[![Build][build-shield]][build]
33
[![Download][download-shield]][download]
44
[![API][api-shield]][api]
5-
###### A context aware string abstraction for _Android_
5+
###### A context aware parcelable string abstraction for _Android_
66

77
```
8-
public interface AString {
8+
public interface AString extends Parcelable {
99
@Nullable
1010
CharSequence invoke(@NonNull Context context);
1111
}

android.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
android {
2-
compileSdkVersion 30
2+
compileSdkVersion 31
33

44
defaultConfig {
55
minSdkVersion 19
6-
targetSdkVersion 30
6+
targetSdkVersion 31
7+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
78
}
89
}

astring/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ plugins {
44
}
55

66
dependencies {
7-
api 'androidx.fragment:fragment:1.3.4'
7+
api 'androidx.fragment:fragment:1.3.6'
88

99
testImplementation project(':testing')
10+
11+
androidTestImplementation 'androidx.test:rules:1.4.0'
1012
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2021 Christian Schmitz
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package xyz.tynn.astring;
5+
6+
import static android.os.Parcel.obtain;
7+
import static org.junit.Assert.assertEquals;
8+
9+
import android.os.Parcel;
10+
import android.os.Parcelable;
11+
12+
class AssertParcelable {
13+
14+
private static ClassLoader getClassloader() {
15+
return AssertParcelable.class.getClassLoader();
16+
}
17+
18+
static <T extends Parcelable> void assertParcelable(T expected) {
19+
Parcel parcel = obtain();
20+
parcel.writeValue(expected);
21+
parcel.setDataPosition(0);
22+
assertEquals(expected, parcel.readValue(getClassloader()));
23+
}
24+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2021 Christian Schmitz
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package xyz.tynn.astring;
5+
6+
import static xyz.tynn.astring.AssertParcelable.assertParcelable;
7+
8+
import org.junit.Test;
9+
10+
import java.util.Date;
11+
12+
public class ParcelableAStringTest {
13+
14+
public static final int RES_ID = 123;
15+
public static final int QUANTITY = 456;
16+
public static final Object[] FORMAT_ARGS = {"arg1", 2, 3L, 4.5, 6F, new Date()};
17+
18+
@Test
19+
public void CharSequence_should_implement_parcelable() {
20+
assertParcelable(new CharSequenceWrapper("test-string"));
21+
}
22+
23+
@Test
24+
public void NullValueWrapper_should_implement_parcelable() {
25+
assertParcelable(NullValueWrapper.I);
26+
}
27+
28+
@Test
29+
public void QuantityStringResourceDelegate_should_implement_parcelable() {
30+
assertParcelable(new QuantityStringResourceDelegate(RES_ID, QUANTITY, FORMAT_ARGS));
31+
}
32+
33+
@Test
34+
public void QuantityTextResourceDelegate_should_implement_parcelable() {
35+
assertParcelable(new QuantityTextResourceDelegate(RES_ID, QUANTITY));
36+
}
37+
38+
@Test
39+
public void StringResourceDelegate_should_implement_parcelable() {
40+
assertParcelable(new StringResourceDelegate(RES_ID, FORMAT_ARGS));
41+
}
42+
43+
@Test
44+
public void TextResourceDelegate_should_implement_parcelable() {
45+
assertParcelable(new TextResourceDelegate(RES_ID));
46+
}
47+
}

astring/src/main/java/xyz/tynn/astring/AString.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package xyz.tynn.astring;
55

66
import android.content.Context;
7+
import android.os.Parcelable;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
@@ -18,7 +19,7 @@
1819
* {@code AString} is almost always used from the main thread,
1920
* therefore all implementations must be non-blocking since
2021
*/
21-
public interface AString {
22+
public interface AString extends Parcelable {
2223

2324
/**
2425
* Provides a context sensitive string
@@ -28,5 +29,10 @@ public interface AString {
2829
*/
2930
@Nullable
3031
CharSequence invoke(@NonNull Context context);
32+
33+
@Override
34+
default int describeContents() {
35+
return 0;
36+
}
3137
}
3238

astring/src/main/java/xyz/tynn/astring/CharSequenceWrapper.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
package xyz.tynn.astring;
55

6+
import static android.text.TextUtils.CHAR_SEQUENCE_CREATOR;
7+
68
import android.content.Context;
9+
import android.os.Parcel;
10+
import android.text.TextUtils;
711

812
import androidx.annotation.NonNull;
913
import androidx.annotation.Nullable;
@@ -45,4 +49,22 @@ public int hashCode() {
4549
public String toString() {
4650
return "AString(" + "CharSequence(" + string + "))";
4751
}
52+
53+
@Override
54+
public void writeToParcel(Parcel dest, int flags) {
55+
TextUtils.writeToParcel(string, dest, flags);
56+
}
57+
58+
public static final Creator<CharSequenceWrapper> CREATOR = new Creator<CharSequenceWrapper>() {
59+
60+
@Override
61+
public CharSequenceWrapper createFromParcel(Parcel source) {
62+
return new CharSequenceWrapper(CHAR_SEQUENCE_CREATOR.createFromParcel(source));
63+
}
64+
65+
@Override
66+
public CharSequenceWrapper[] newArray(int size) {
67+
return new CharSequenceWrapper[size];
68+
}
69+
};
4870
}

astring/src/main/java/xyz/tynn/astring/NullValueWrapper.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package xyz.tynn.astring;
55

66
import android.content.Context;
7+
import android.os.Parcel;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
@@ -16,6 +17,9 @@ final class NullValueWrapper implements AString {
1617
@NonNull
1718
static NullValueWrapper I = new NullValueWrapper();
1819

20+
private NullValueWrapper() {
21+
}
22+
1923
@Nullable
2024
@Override
2125
public CharSequence invoke(@Nullable Context context) {
@@ -37,4 +41,21 @@ public int hashCode() {
3741
public String toString() {
3842
return "AString(" + "NullValue(" + null + "))";
3943
}
44+
45+
@Override
46+
public void writeToParcel(Parcel dest, int flags) {
47+
}
48+
49+
public static final Creator<NullValueWrapper> CREATOR = new Creator<NullValueWrapper>() {
50+
51+
@Override
52+
public NullValueWrapper createFromParcel(Parcel source) {
53+
return I;
54+
}
55+
56+
@Override
57+
public NullValueWrapper[] newArray(int size) {
58+
return new NullValueWrapper[size];
59+
}
60+
};
4061
}

astring/src/main/java/xyz/tynn/astring/QuantityStringResourceDelegate.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import android.content.Context;
77
import android.content.res.Resources;
8+
import android.os.Parcel;
89

910
import androidx.annotation.NonNull;
1011
import androidx.annotation.Nullable;
@@ -62,4 +63,25 @@ public String toString() {
6263
sb.append(',').append(o);
6364
return sb.append("))").toString();
6465
}
66+
67+
@Override
68+
public void writeToParcel(Parcel dest, int flags) {
69+
dest.writeInt(resId);
70+
dest.writeInt(quantity);
71+
dest.writeValue(formatArgs);
72+
}
73+
74+
public static final Creator<QuantityStringResourceDelegate> CREATOR = new Creator<QuantityStringResourceDelegate>() {
75+
76+
@Override
77+
public QuantityStringResourceDelegate createFromParcel(Parcel source) {
78+
return new QuantityStringResourceDelegate(source.readInt(), source.readInt(),
79+
(Object[]) source.readValue(getClass().getClassLoader()));
80+
}
81+
82+
@Override
83+
public QuantityStringResourceDelegate[] newArray(int size) {
84+
return new QuantityStringResourceDelegate[size];
85+
}
86+
};
6587
}

astring/src/main/java/xyz/tynn/astring/QuantityTextResourceDelegate.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package xyz.tynn.astring;
55

66
import android.content.Context;
7+
import android.os.Parcel;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
@@ -46,4 +47,23 @@ public int hashCode() {
4647
public String toString() {
4748
return "AString(" + "QuantityTextResource(" + resId + ',' + quantity + "))";
4849
}
50+
51+
@Override
52+
public void writeToParcel(Parcel dest, int flags) {
53+
dest.writeInt(resId);
54+
dest.writeInt(quantity);
55+
}
56+
57+
public static final Creator<QuantityTextResourceDelegate> CREATOR = new Creator<QuantityTextResourceDelegate>() {
58+
59+
@Override
60+
public QuantityTextResourceDelegate createFromParcel(Parcel source) {
61+
return new QuantityTextResourceDelegate(source.readInt(), source.readInt());
62+
}
63+
64+
@Override
65+
public QuantityTextResourceDelegate[] newArray(int size) {
66+
return new QuantityTextResourceDelegate[size];
67+
}
68+
};
4969
}

astring/src/main/java/xyz/tynn/astring/StringResourceDelegate.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package xyz.tynn.astring;
55

66
import android.content.Context;
7+
import android.os.Parcel;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
@@ -57,4 +58,24 @@ public String toString() {
5758
sb.append(',').append(o);
5859
return sb.append("))").toString();
5960
}
61+
62+
@Override
63+
public void writeToParcel(Parcel dest, int flags) {
64+
dest.writeInt(resId);
65+
dest.writeValue(formatArgs);
66+
}
67+
68+
public static final Creator<StringResourceDelegate> CREATOR = new Creator<StringResourceDelegate>() {
69+
70+
@Override
71+
public StringResourceDelegate createFromParcel(Parcel source) {
72+
return new StringResourceDelegate(source.readInt(),
73+
(Object[]) source.readValue(getClass().getClassLoader()));
74+
}
75+
76+
@Override
77+
public StringResourceDelegate[] newArray(int size) {
78+
return new StringResourceDelegate[size];
79+
}
80+
};
6081
}

astring/src/main/java/xyz/tynn/astring/TextResourceDelegate.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package xyz.tynn.astring;
55

66
import android.content.Context;
7+
import android.os.Parcel;
78

89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
@@ -44,4 +45,22 @@ public int hashCode() {
4445
public String toString() {
4546
return "AString(" + "TextResource(" + resId + "))";
4647
}
48+
49+
@Override
50+
public void writeToParcel(Parcel dest, int flags) {
51+
dest.writeInt(resId);
52+
}
53+
54+
public static final Creator<TextResourceDelegate> CREATOR = new Creator<TextResourceDelegate>() {
55+
56+
@Override
57+
public TextResourceDelegate createFromParcel(Parcel source) {
58+
return new TextResourceDelegate(source.readInt());
59+
}
60+
61+
@Override
62+
public TextResourceDelegate[] newArray(int size) {
63+
return new TextResourceDelegate[size];
64+
}
65+
};
4766
}

astring/src/main/kotlin/xyz/tynn/astring/AStringFactory.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package xyz.tynn.astring
88

9+
import android.os.Parcel
10+
import android.text.TextUtils
911
import androidx.annotation.PluralsRes
1012
import androidx.annotation.StringRes
1113

@@ -16,6 +18,9 @@ public val nullAsAString: AString = NullValueWrapper.I
1618
* Creates an `AString` from a `CharSequence?`
1719
*
1820
* Returns [nullAsAString] for null
21+
*
22+
* **Note** that [TextUtils.writeToParcel] is used to parcel
23+
* the [CharSequence] which might lose some custom styles
1924
*/
2025
@JvmName("createFromCharSequence")
2126
public fun CharSequence?.asAString(): AString = if (this == null)
@@ -43,6 +48,9 @@ else QuantityStringResourceDelegate(
4348
* Creates an `AString` from a plurals string resource with format arguments
4449
*
4550
* Returns [nullAsAString] for 0
51+
*
52+
* **Note** that [Parcel.writeValue] is used to parcel [formatArgs]
53+
* which might throw a [RuntimeException] for un-parcelable values
4654
*/
4755
@JvmName("createFromQuantityStringResource")
4856
public fun QuantityStringResource(
@@ -92,6 +100,9 @@ else StringResourceDelegate(
92100
* Creates an `AString` from a string resource with format arguments
93101
*
94102
* Returns [nullAsAString] for 0
103+
*
104+
* **Note** that [Parcel.writeValue] is used to parcel [formatArgs]
105+
* which might throw a [RuntimeException] for un-parcelable values
95106
*/
96107
@JvmName("createFromStringResource")
97108
public fun StringResource(

0 commit comments

Comments
 (0)