Skip to content
Snippets Groups Projects
Commit 0f64e2df authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Updated and refactored code

parent 1fa7d17b
Branches
Tags
No related merge requests found
Showing
with 599 additions and 98 deletions
package de.kuschku.util;
import java.util.Arrays;
import java.util.Comparator;
/**
* Utility methods for objects.
* @see java.util.Objects
* @since 1.7
*/
public final class Objects {
private Objects() {}
/**
* Returns 0 if {@code a == b}, or {@code c.compare(a, b)} otherwise.
* That is, this makes {@code c} null-safe.
*/
public static <T> int compare(T a, T b, Comparator<? super T> c) {
if (a == b) {
return 0;
}
return c.compare(a, b);
}
/**
* Returns true if both arguments are null,
* the result of {@link Arrays#equals} if both arguments are primitive arrays,
* the result of {@link Arrays#deepEquals} if both arguments are arrays of reference types,
* and the result of {@link #equals} otherwise.
*/
public static boolean deepEquals(Object a, Object b) {
if (a == null || b == null) {
return a == b;
} else if (a instanceof Object[] && b instanceof Object[]) {
return Arrays.deepEquals((Object[]) a, (Object[]) b);
} else if (a instanceof boolean[] && b instanceof boolean[]) {
return Arrays.equals((boolean[]) a, (boolean[]) b);
} else if (a instanceof byte[] && b instanceof byte[]) {
return Arrays.equals((byte[]) a, (byte[]) b);
} else if (a instanceof char[] && b instanceof char[]) {
return Arrays.equals((char[]) a, (char[]) b);
} else if (a instanceof double[] && b instanceof double[]) {
return Arrays.equals((double[]) a, (double[]) b);
} else if (a instanceof float[] && b instanceof float[]) {
return Arrays.equals((float[]) a, (float[]) b);
} else if (a instanceof int[] && b instanceof int[]) {
return Arrays.equals((int[]) a, (int[]) b);
} else if (a instanceof long[] && b instanceof long[]) {
return Arrays.equals((long[]) a, (long[]) b);
} else if (a instanceof short[] && b instanceof short[]) {
return Arrays.equals((short[]) a, (short[]) b);
}
return a.equals(b);
}
/**
* Null-safe equivalent of {@code a.equals(b)}.
*/
public static boolean equals(Object a, Object b) {
return (a == null) ? (b == null) : a.equals(b);
}
/**
* Convenience wrapper for {@link Arrays#hashCode}, adding varargs.
* This can be used to compute a hash code for an object's fields as follows:
* {@code Objects.hash(a, b, c)}.
*/
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
/**
* Returns 0 for null or {@code o.hashCode()}.
*/
public static int hashCode(Object o) {
return (o == null) ? 0 : o.hashCode();
}
/**
* Returns {@code o} if non-null, or throws {@code NullPointerException}.
*/
public static <T> T requireNonNull(T o) {
if (o == null) {
throw new NullPointerException();
}
return o;
}
/**
* Returns {@code o} if non-null, or throws {@code NullPointerException}
* with the given detail message.
*/
public static <T> T requireNonNull(T o, String message) {
if (o == null) {
throw new NullPointerException(message);
}
return o;
}
/**
* Returns "null" for null or {@code o.toString()}.
*/
public static String toString(Object o) {
return (o == null) ? "null" : o.toString();
}
/**
* Returns {@code nullString} for null or {@code o.toString()}.
*/
public static String toString(Object o, String nullString) {
return (o == null) ? nullString : o.toString();
}
}
...@@ -9,14 +9,23 @@ import java.util.Arrays; ...@@ -9,14 +9,23 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import de.kuschku.libquassel.exceptions.SyncInvocationException; import de.kuschku.libquassel.exceptions.SyncInvocationException;
import de.kuschku.libquassel.primitives.types.QVariant;
public class ReflectionUtils { public class ReflectionUtils {
private ReflectionUtils() { private ReflectionUtils() {
} }
private static void unboxList(Object[] list){
for (int i = 0; i < list.length; i++) {
if (list[i] instanceof QVariant)
list[i] = ((QVariant) list[i]).data;
}
}
public static void invokeMethod(Object o, String name, Object[] argv) throws SyncInvocationException { public static void invokeMethod(Object o, String name, Object[] argv) throws SyncInvocationException {
name = stripName(name); name = stripName(name);
unboxList(argv);
Class<?>[] classes = new Class<?>[argv.length]; Class<?>[] classes = new Class<?>[argv.length];
for (int i = 0; i < argv.length; i++) { for (int i = 0; i < argv.length; i++) {
...@@ -24,12 +33,12 @@ public class ReflectionUtils { ...@@ -24,12 +33,12 @@ public class ReflectionUtils {
} }
Method m = getMethodFromSignature(name, o.getClass(), classes); Method m = getMethodFromSignature(name, o.getClass(), classes);
if (m == null) if (m == null)
throw new SyncInvocationException(String.format("Error invoking %s::%s with arguments %s", o.getClass().getSimpleName(), name, Arrays.toString(argv))); throw new SyncInvocationException(String.format("No method %s::%s with argument types %s", o.getClass().getSimpleName(), name, Arrays.toString(classes)));
try { try {
m.invoke(o, argv); m.invoke(o, argv);
} catch (Exception e) { } catch (Exception e) {
throw new SyncInvocationException(e, String.format("Error invoking %s::%s with arguments %s", o.getClass().getSimpleName(), name, Arrays.toString(argv))); throw new SyncInvocationException(e, String.format("Error invoking %s::%s with arguments %s and classes %s", o.getClass().getSimpleName(), name, Arrays.toString(argv), Arrays.toString(classes)));
} }
} }
......
package de.kuschku.quasseldroid_ng.util; package de.kuschku.util;
public class ServerAddress { public class ServerAddress {
public final String host; public final String host;
......
...@@ -4,18 +4,20 @@ import android.content.Context; ...@@ -4,18 +4,20 @@ import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.util.Log;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Arrays;
public class Binder { public class AutoBinder {
private Binder() { private AutoBinder() {
} }
public static void bind(Object o, Resources.Theme t) throws IllegalAccessException { public static void bind(Object o, Resources.Theme t) throws IllegalAccessException {
for (Field f : o.getClass().getFields()) { for (Field f : o.getClass().getFields()) {
if (f.isAnnotationPresent(Color.class)) { if (f.isAnnotationPresent(AutoColor.class)) {
int[] colors = obtainColors(f.getAnnotation(Color.class).value(), t); int[] colors = obtainColors(f.getAnnotation(AutoColor.class).value(), t);
if (f.getType().isArray()) if (f.getType().isArray())
f.set(o, colors); f.set(o, colors);
else if (colors.length == 1) else if (colors.length == 1)
...@@ -27,7 +29,26 @@ public class Binder { ...@@ -27,7 +29,26 @@ public class Binder {
} }
public static void bind(Object o, Context t) throws IllegalAccessException { public static void bind(Object o, Context t) throws IllegalAccessException {
bind(o, t.getTheme()); Resources.Theme theme = t.getTheme();
for (Field f : o.getClass().getFields()) {
if (f.isAnnotationPresent(AutoColor.class)) {
int[] colors = obtainColors(f.getAnnotation(AutoColor.class).value(), theme);
if (f.getType().isArray())
f.set(o, colors);
else if (colors.length == 1)
f.set(o, colors[0]);
else
throw new IllegalAccessException("Field length does not correspond to argument length");
} else if (f.isAnnotationPresent(AutoString.class)) {
String[] strings = obtainStrings(f.getAnnotation(AutoString.class).value(), t);
if (f.getType().isArray())
f.set(o, strings);
else if (strings.length == 1)
f.set(o, strings[0]);
else
throw new IllegalAccessException("Field length does not correspond to argument length");
}
}
} }
@ColorInt @ColorInt
...@@ -40,4 +61,12 @@ public class Binder { ...@@ -40,4 +61,12 @@ public class Binder {
t.recycle(); t.recycle();
return result; return result;
} }
private static String[] obtainStrings(int[] res, Context ctx) {
String[] result = new String[res.length];
for (int i = 0; i < res.length; i++) {
result[i] = ctx.getString(res[i]);
}
return result;
}
} }
...@@ -6,7 +6,7 @@ import java.lang.annotation.Retention; ...@@ -6,7 +6,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Color { public @interface AutoColor {
@AnyRes @AnyRes
int[] value() default {}; int[] value() default {};
} }
package de.kuschku.util.annotationbind;
import android.support.annotation.AnyRes;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoString {
@AnyRes
int[] value() default {};
}
package de.kuschku.util.instancestateutil;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.SparseArray;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
public class Storable {
public boolean onRestoreInstanceState(Bundle in) {
try {
Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Store.class)) {
Store annotation = field.getAnnotation(Store.class);
String name = annotation.name().isEmpty() ? field.getName() : annotation.name();
Store.Type type = annotation.type() == Store.Type.INVALID ? getTypeFromClass(field.getType()) : annotation.type();
loadField(in, type, name, field);
}
}
return true;
} catch (IllegalAccessException e) {
return false;
}
}
public boolean onSaveInstanceState(Bundle out) {
try {
Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Store.class)) {
Store annotation = field.getAnnotation(Store.class);
String name = annotation.name().isEmpty() ? field.getName() : annotation.name();
Store.Type type = annotation.type() == Store.Type.INVALID ? getTypeFromClass(field.getType()) : annotation.type();
storeField(out, type, name, field.get(this));
}
}
return true;
} catch (IllegalAccessException e) {
return false;
}
}
private void storeField(Bundle out, Store.Type type, String name, Object data) {
switch (type) {
case BOOLEAN:
out.putBoolean(name, (Boolean) data);
break;
case BOOLEAN_ARRAY:
out.putBooleanArray(name, (boolean[]) data);
break;
case BYTE:
out.putByte(name, (byte) data);
break;
case BYTE_ARRAY:
out.putByteArray(name, (byte[]) data);
break;
case CHAR:
out.putChar(name, (char) data);
break;
case CHAR_ARRAY:
out.putCharArray(name, (char[]) data);
break;
case SHORT:
out.putShort(name, (short) data);
break;
case SHORT_ARRAY:
out.putShortArray(name, (short[]) data);
break;
case INT:
out.putInt(name, (int) data);
break;
case INT_ARRAY:
out.putIntArray(name, (int[]) data);
break;
case INTEGER_ARRAYLIST:
out.putIntegerArrayList(name, (ArrayList<Integer>) data);
break;
case LONG:
out.putLong(name, (long) data);
break;
case LONG_ARRAY:
out.putLongArray(name, (long[]) data);
break;
case FLOAT:
out.putFloat(name, (float) data);
break;
case FLOAT_ARRAY:
out.putFloatArray(name, (float[]) data);
break;
case DOUBLE:
out.putDouble(name, (double) data);
break;
case DOUBLE_ARRAY:
out.putDoubleArray(name, (double[]) data);
break;
case STRING:
out.putString(name, (String) data);
break;
case STRING_ARRAY:
out.putStringArray(name, (String[]) data);
break;
case STRING_ARRAYLIST:
out.putStringArrayList(name, (ArrayList<String>) data);
break;
case CHARSEQUENCE:
out.putCharSequence(name, (CharSequence) data);
break;
case CHARSEQUENCE_ARRAY:
out.putCharSequenceArray(name, (CharSequence[]) data);
break;
case CHARSEQUENCE_ARRAYLIST:
out.putCharSequenceArrayList(name, (ArrayList<CharSequence>) data);
break;
case PARCELABLE:
out.putParcelable(name, (Parcelable) data);
break;
case PARCELABLE_ARRAY:
out.putParcelableArray(name, (Parcelable[]) data);
break;
case PARCELABLE_ARRAYLIST:
out.putParcelableArrayList(name, (ArrayList<? extends Parcelable>) data);
break;
case SPARSEPARCELABLE_ARRAY:
out.putSparseParcelableArray(name, (SparseArray<? extends Parcelable>) data);
break;
case SERIALIZABLE:
out.putSerializable(name, (Serializable) data);
break;
case BUNDLE:
out.putBundle(name, (Bundle) data);
break;
}
}
private void loadField(Bundle in, Store.Type type, String name, Field field) throws IllegalAccessException {
if (!in.containsKey(name)) return;
switch (type) {
case BOOLEAN:
field.setBoolean(this, in.getBoolean(name));
break;
case BOOLEAN_ARRAY:
field.set(this, in.getBooleanArray(name));
break;
case BYTE:
field.setByte(this, in.getByte(name));
break;
case BYTE_ARRAY:
field.set(this, in.getByteArray(name));
break;
case CHAR:
field.setChar(this, in.getChar(name));
break;
case CHAR_ARRAY:
field.set(this, in.getCharArray(name));
break;
case SHORT:
field.setShort(this, in.getShort(name));
break;
case SHORT_ARRAY:
field.set(this, in.getShortArray(name));
break;
case INT:
field.setInt(this, in.getInt(name));
break;
case INT_ARRAY:
field.set(this, in.getIntArray(name));
break;
case INTEGER_ARRAYLIST:
field.set(this, in.getIntegerArrayList(name));
break;
case LONG:
field.setLong(this, in.getLong(name));
break;
case LONG_ARRAY:
field.set(this, in.getLongArray(name));
break;
case FLOAT:
field.setFloat(this, in.getFloat(name));
break;
case FLOAT_ARRAY:
field.set(this, in.getFloatArray(name));
break;
case DOUBLE:
field.setDouble(this, in.getDouble(name));
break;
case DOUBLE_ARRAY:
field.set(this, in.getDoubleArray(name));
break;
case STRING:
field.set(this, in.getString(name));
break;
case STRING_ARRAY:
field.set(this, in.getStringArray(name));
break;
case STRING_ARRAYLIST:
field.set(this, in.getStringArrayList(name));
break;
case CHARSEQUENCE:
field.set(this, in.getCharSequence(name));
break;
case CHARSEQUENCE_ARRAY:
field.set(this, in.getCharSequenceArray(name));
break;
case CHARSEQUENCE_ARRAYLIST:
field.set(this, in.getCharSequenceArrayList(name));
break;
case PARCELABLE:
field.set(this, in.getParcelable(name));
break;
case PARCELABLE_ARRAY:
field.set(this, in.getParcelableArray(name));
break;
case PARCELABLE_ARRAYLIST:
field.set(this, in.getParcelableArrayList(name));
break;
case SPARSEPARCELABLE_ARRAY:
field.set(this, in.getSparseParcelableArray(name));
break;
case SERIALIZABLE:
field.set(this, in.getSerializable(name));
break;
case BUNDLE:
field.set(this, in.getBundle(name));
break;
}
}
private Store.Type getTypeFromClass(Class cl) {
if (boolean.class.isAssignableFrom(cl)) return Store.Type.BOOLEAN;
if (boolean[].class.isAssignableFrom(cl)) return Store.Type.BOOLEAN_ARRAY;
if (byte.class.isAssignableFrom(cl)) return Store.Type.BYTE;
if (byte[].class.isAssignableFrom(cl)) return Store.Type.BYTE_ARRAY;
if (char.class.isAssignableFrom(cl)) return Store.Type.CHAR;
if (char[].class.isAssignableFrom(cl)) return Store.Type.CHAR_ARRAY;
if (short.class.isAssignableFrom(cl)) return Store.Type.SHORT;
if (short[].class.isAssignableFrom(cl)) return Store.Type.SHORT_ARRAY;
if (int.class.isAssignableFrom(cl)) return Store.Type.INT;
if (int[].class.isAssignableFrom(cl)) return Store.Type.INT_ARRAY;
if (long.class.isAssignableFrom(cl)) return Store.Type.LONG;
if (long[].class.isAssignableFrom(cl)) return Store.Type.LONG_ARRAY;
if (float.class.isAssignableFrom(cl)) return Store.Type.FLOAT;
if (float[].class.isAssignableFrom(cl)) return Store.Type.FLOAT_ARRAY;
if (double.class.isAssignableFrom(cl)) return Store.Type.DOUBLE;
if (double[].class.isAssignableFrom(cl)) return Store.Type.DOUBLE_ARRAY;
if (String.class.isAssignableFrom(cl)) return Store.Type.STRING;
if (String[].class.isAssignableFrom(cl)) return Store.Type.STRING_ARRAY;
if (CharSequence.class.isAssignableFrom(cl)) return Store.Type.CHARSEQUENCE;
if (CharSequence[].class.isAssignableFrom(cl)) return Store.Type.CHARSEQUENCE_ARRAY;
if (Parcelable.class.isAssignableFrom(cl)) return Store.Type.PARCELABLE;
if (Parcelable[].class.isAssignableFrom(cl)) return Store.Type.PARCELABLE_ARRAY;
if (Serializable.class.isAssignableFrom(cl)) return Store.Type.SERIALIZABLE;
if (Bundle.class.isAssignableFrom(cl)) return Store.Type.BUNDLE;
return Store.Type.INVALID;
}
}
package de.kuschku.util.instancestateutil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Store {
String name() default "";
Type type() default Type.INVALID;
enum Type {
INVALID,
BOOLEAN,
BOOLEAN_ARRAY,
BYTE,
BYTE_ARRAY,
CHAR,
CHAR_ARRAY,
SHORT,
SHORT_ARRAY,
INT,
INT_ARRAY,
INTEGER_ARRAYLIST,
LONG,
LONG_ARRAY,
FLOAT,
FLOAT_ARRAY,
DOUBLE,
DOUBLE_ARRAY,
STRING,
STRING_ARRAY,
STRING_ARRAYLIST,
CHARSEQUENCE,
CHARSEQUENCE_ARRAY,
CHARSEQUENCE_ARRAYLIST,
PARCELABLE,
PARCELABLE_ARRAY,
PARCELABLE_ARRAYLIST,
SPARSEPARCELABLE_ARRAY,
SERIALIZABLE,
BUNDLE,
}
}
package de.kuschku.quasseldroid_ng.util; package de.kuschku.util.irc;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
...@@ -8,14 +8,13 @@ import android.graphics.Typeface; ...@@ -8,14 +8,13 @@ import android.graphics.Typeface;
import android.net.Uri; import android.net.Uri;
import android.os.Parcel; import android.os.Parcel;
import android.provider.Browser; import android.provider.Browser;
import android.support.annotation.NonNull;
import android.text.ParcelableSpan; import android.text.ParcelableSpan;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ClickableSpan; import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
...@@ -25,6 +24,7 @@ import java.util.regex.Matcher; ...@@ -25,6 +24,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import de.kuschku.quasseldroid_ng.R; import de.kuschku.quasseldroid_ng.R;
import de.kuschku.util.ui.ThemeUtil;
public class IrcFormatHelper { public class IrcFormatHelper {
private static final String scheme = "(?:(?:mailto:|(?:[+.-]?\\w)+://)|www(?=\\.\\S+\\.))"; private static final String scheme = "(?:(?:mailto:|(?:[+.-]?\\w)+://)|www(?=\\.\\S+\\.))";
...@@ -36,11 +36,11 @@ public class IrcFormatHelper { ...@@ -36,11 +36,11 @@ public class IrcFormatHelper {
private final ThemeUtil.Colors colors; private final ThemeUtil.Colors colors;
public IrcFormatHelper(ThemeUtil.Colors colors) { public IrcFormatHelper(@NonNull ThemeUtil.Colors colors) {
this.colors = colors; this.colors = colors;
} }
public CharSequence formatUserNick(String nick) { public CharSequence formatUserNick(@NonNull String nick) {
int colorIndex = IrcUserUtils.getSenderColor(nick); int colorIndex = IrcUserUtils.getSenderColor(nick);
int color = colors.senderColors[colorIndex]; int color = colors.senderColors[colorIndex];
...@@ -50,7 +50,7 @@ public class IrcFormatHelper { ...@@ -50,7 +50,7 @@ public class IrcFormatHelper {
return str; return str;
} }
public CharSequence formatIrcMessage(String message) { public CharSequence formatIrcMessage(@NonNull String message) {
List<FutureClickableSpan> spans = new LinkedList<>(); List<FutureClickableSpan> spans = new LinkedList<>();
SpannableString str = new SpannableString(message); SpannableString str = new SpannableString(message);
...@@ -69,21 +69,21 @@ public class IrcFormatHelper { ...@@ -69,21 +69,21 @@ public class IrcFormatHelper {
public final int start; public final int start;
public final int end; public final int end;
public FutureClickableSpan(ClickableSpan span, int start, int end) { public FutureClickableSpan(@NonNull ClickableSpan span, int start, int end) {
this.span = span; this.span = span;
this.start = start; this.start = start;
this.end = end; this.end = end;
} }
} }
private class CustomURLSpan extends ClickableSpan implements ParcelableSpan { private static class CustomURLSpan extends ClickableSpan implements ParcelableSpan {
private final String mURL; private final String mURL;
public CustomURLSpan(String url) { public CustomURLSpan(@NonNull String url) {
mURL = url; mURL = url;
} }
public CustomURLSpan(Parcel src) { public CustomURLSpan(@NonNull Parcel src) {
mURL = src.readString(); mURL = src.readString();
} }
...@@ -95,7 +95,7 @@ public class IrcFormatHelper { ...@@ -95,7 +95,7 @@ public class IrcFormatHelper {
return 0; return 0;
} }
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mURL); dest.writeString(mURL);
} }
......
package de.kuschku.quasseldroid_ng.util; package de.kuschku.util.irc;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Locale; import java.util.Locale;
......
package de.kuschku.util.niohelpers; package de.kuschku.util.niohelpers;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import java.io.DataInputStream; import java.io.DataInputStream;
...@@ -40,6 +42,7 @@ public class WrappedChannel implements Flushable, ByteChannel, InterruptibleChan ...@@ -40,6 +42,7 @@ public class WrappedChannel implements Flushable, ByteChannel, InterruptibleChan
return new WrappedChannel(s.getInputStream(), s.getOutputStream()); return new WrappedChannel(s.getInputStream(), s.getOutputStream());
} }
@TargetApi(Build.VERSION_CODES.KITKAT)
public static WrappedChannel withCompression(WrappedChannel channel) throws IOException { public static WrappedChannel withCompression(WrappedChannel channel) throws IOException {
return new WrappedChannel( return new WrappedChannel(
new InflaterInputStream(channel.rawIn), new InflaterInputStream(channel.rawIn),
......
package de.kuschku.util.observablelists;
import android.support.v7.util.SortedList;
public class ObservableSortedList<T extends ContentComparable<T>> {
public final SortedList<T> list;
Callback internal = new Callback();
UICallback callback;
boolean reverse;
public ObservableSortedList(Class<T> cl) {
list = new SortedList<>(cl, internal);
}
public ObservableSortedList(Class<T> cl, boolean reverse) {
this(cl);
this.reverse = reverse;
}
public void setCallback(UICallback callback) {
this.callback = callback;
}
public T last() {
if (list.size() == 0) return null;
return list.get(list.size() - 1);
}
class Callback extends SortedList.Callback<T> {
@Override
public int compare(T o1, T o2) {
return (reverse) ? o2.compareTo(o1): o1.compareTo(o2);
}
@Override
public void onInserted(int position, int count) {
if (callback != null)
if (count == 1)
callback.notifyItemInserted(position);
else
callback.notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
if (callback != null)
if (count == 1)
callback.notifyItemRemoved(position);
else
callback.notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
if (callback != null)
callback.notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
if (callback != null)
if (count == 1)
callback.notifyItemChanged(position);
else
callback.notifyItemRangeChanged(position, count);
}
@Override
public boolean areContentsTheSame(T oldItem, T newItem) {
return oldItem.equalsContent(newItem);
}
@Override
public boolean areItemsTheSame(T item1, T item2) {
return item1.equals(item2);
}
}
}
package de.kuschku.util.observablelists; package de.kuschku.util.observables;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
......
package de.kuschku.util.observablelists; package de.kuschku.util.observables;
public interface ContentComparable<T extends ContentComparable<T>> extends Comparable<T> { public interface ContentComparable<T extends ContentComparable<T>> extends Comparable<T> {
boolean equalsContent(T other); boolean equalsContent(T other);
......
package de.kuschku.util.observables;
import de.kuschku.util.observables.callbacks.UICallback;
public interface IObservable<T> {
void addCallback(T callback);
void removeCallback(T callback);
}
package de.kuschku.util.observables.callbacks;
import android.support.annotation.UiThread;
public interface ElementCallback<T> {
@UiThread
void notifyItemInserted(T element);
@UiThread
void notifyItemRemoved(T element);
@UiThread
void notifyItemChanged(T element);
}
package de.kuschku.util.observablelists; package de.kuschku.util.observables.callbacks;
import android.support.annotation.UiThread;
public interface UICallback { public interface UICallback {
@UiThread
void notifyItemInserted(int position); void notifyItemInserted(int position);
@UiThread
void notifyItemChanged(int position); void notifyItemChanged(int position);
@UiThread
void notifyItemRemoved(int position); void notifyItemRemoved(int position);
@UiThread
void notifyItemMoved(int from, int to); void notifyItemMoved(int from, int to);
@UiThread
void notifyItemRangeInserted(int position, int count); void notifyItemRangeInserted(int position, int count);
@UiThread
void notifyItemRangeChanged(int position, int count); void notifyItemRangeChanged(int position, int count);
@UiThread
void notifyItemRangeRemoved(int position, int count); void notifyItemRangeRemoved(int position, int count);
} }
package de.kuschku.util.observables.callbacks;
import android.support.annotation.UiThread;
public interface UIChildCallback {
@UiThread
void notifyChildItemInserted(int group, int position);
@UiThread
void notifyChildItemChanged(int group, int position);
@UiThread
void notifyChildItemRemoved(int group, int position);
}
package de.kuschku.util.observables.callbacks;
public interface UIChildParentCallback extends UIChildCallback, UIParentCallback {
}
package de.kuschku.util.observables.callbacks;
import android.support.annotation.UiThread;
public interface UIParentCallback {
@UiThread
void notifyParentItemInserted(int position);
@UiThread
void notifyParentItemRemoved(int position);
@UiThread
void notifyParentItemChanged(int position);
@UiThread
void notifyParentItemRangeInserted(int from, int to);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment