1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

improved json serialization

This commit is contained in:
Mariotaku Lee 2016-02-19 15:09:32 +08:00
parent 01cfec55dd
commit 62fbf6ca10
19 changed files with 391 additions and 226 deletions

View File

@ -124,7 +124,7 @@ public class OAuthToken implements ValueMap {
return new String[]{"oauth_token", "oauth_token_secret"};
}
public static class Converter implements RestConverter<HttpResponse, OAuthToken, TwitterException> {
public static class ResponseConverter implements RestConverter<HttpResponse, OAuthToken, TwitterException> {
@Override
public OAuthToken convert(HttpResponse response) throws IOException, ConvertException {
final Body body = response.getBody();

View File

@ -35,7 +35,10 @@ import java.util.Locale;
*/
public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
public static final Activity$$JsonObjectMapper INSTANCE = new Activity$$JsonObjectMapper();
private static final JsonMapper<User> USER_JSON_MAPPER = LoganSquare.mapperFor(User.class);
private static final JsonMapper<Status> STATUS_JSON_MAPPER = LoganSquare.mapperFor(Status.class);
private static final JsonMapper<UserList> USER_LIST_JSON_MAPPER = LoganSquare.mapperFor(UserList.class);
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
@SuppressWarnings("TryWithIdenticalCatches")
@ -84,7 +87,7 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
} else if ("target_objects_size".equals(fieldName)) {
instance.targetObjectsSize = jsonParser.getValueAsInt();
} else if ("sources".equals(fieldName)) {
instance.sources = LoganSquare.mapperFor(User.class).parseList(jsonParser).toArray(new User[instance.sourcesSize]);
instance.sources = USER_JSON_MAPPER.parseList(jsonParser).toArray(new User[instance.sourcesSize]);
} else if ("targets".equals(fieldName)) {
if (instance.action == null) throw new IOException();
switch (instance.action) {
@ -99,17 +102,17 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
case Activity.Action.MEDIA_TAGGED:
case Activity.Action.FAVORITED_MEDIA_TAGGED:
case Activity.Action.RETWEETED_MEDIA_TAGGED: {
instance.targetStatuses = LoganSquare.mapperFor(Status.class).parseList(jsonParser).toArray(new Status[instance.targetsSize]);
instance.targetStatuses = STATUS_JSON_MAPPER.parseList(jsonParser).toArray(new Status[instance.targetsSize]);
break;
}
case Activity.Action.FOLLOW:
case Activity.Action.MENTION:
case Activity.Action.LIST_MEMBER_ADDED: {
instance.targetUsers = LoganSquare.mapperFor(User.class).parseList(jsonParser).toArray(new User[instance.targetsSize]);
instance.targetUsers = USER_JSON_MAPPER.parseList(jsonParser).toArray(new User[instance.targetsSize]);
break;
}
case Activity.Action.LIST_CREATED: {
instance.targetUserLists = LoganSquare.mapperFor(UserList.class).parseList(jsonParser).toArray(new UserList[instance.targetsSize]);
instance.targetUserLists = USER_LIST_JSON_MAPPER.parseList(jsonParser).toArray(new UserList[instance.targetsSize]);
break;
}
}
@ -123,11 +126,11 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
case Activity.Action.RETWEET:
case Activity.Action.LIST_CREATED:
case Activity.Action.QUOTE: {
instance.targetObjectStatuses = LoganSquare.mapperFor(Status.class).parseList(jsonParser).toArray(new Status[instance.targetObjectsSize]);
instance.targetObjectStatuses = STATUS_JSON_MAPPER.parseList(jsonParser).toArray(new Status[instance.targetObjectsSize]);
break;
}
case Activity.Action.LIST_MEMBER_ADDED: {
instance.targetObjectUserLists = LoganSquare.mapperFor(UserList.class).parseList(jsonParser).toArray(new UserList[instance.targetObjectsSize]);
instance.targetObjectUserLists = USER_LIST_JSON_MAPPER.parseList(jsonParser).toArray(new UserList[instance.targetObjectsSize]);
break;
}
case Activity.Action.FAVORITED_RETWEET:
@ -137,7 +140,7 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
case Activity.Action.MEDIA_TAGGED:
case Activity.Action.FAVORITED_MEDIA_TAGGED:
case Activity.Action.RETWEETED_MEDIA_TAGGED: {
instance.targetObjectUsers = LoganSquare.mapperFor(User.class).parseList(jsonParser).toArray(new User[instance.targetObjectsSize]);
instance.targetObjectUsers = USER_JSON_MAPPER.parseList(jsonParser).toArray(new User[instance.targetObjectsSize]);
break;
}
}

View File

@ -20,10 +20,17 @@
package org.mariotaku.twidere.api.twitter.model;
import com.bluelinelabs.logansquare.LoganSquare;
import com.fasterxml.jackson.core.JsonGenerator;
import org.mariotaku.restfu.RestConverter;
import org.mariotaku.restfu.http.ValueMap;
import org.mariotaku.restfu.http.mime.Body;
import org.mariotaku.restfu.http.mime.StringBody;
import org.mariotaku.twidere.api.twitter.TwitterException;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@ -42,15 +49,6 @@ public class CardDataMap implements ValueMap {
map.put("twitter:long:" + key, String.valueOf(value));
}
@Override
public String toString() {
try {
return LoganSquare.serialize(map);
} catch (IOException e) {
throw new AssertionError(e);
}
}
@Override
public boolean has(String key) {
return map.containsKey(key);
@ -66,4 +64,26 @@ public class CardDataMap implements ValueMap {
final Set<String> keySet = map.keySet();
return keySet.toArray(new String[keySet.size()]);
}
@Override
public String toString() {
return "CardDataMap{" +
"map=" + map +
'}';
}
public static class BodyConverter implements RestConverter<CardDataMap, Body, TwitterException> {
@Override
public Body convert(CardDataMap obj) throws ConvertException, IOException, TwitterException {
final StringWriter sw = new StringWriter();
final JsonGenerator generator = LoganSquare.JSON_FACTORY.createGenerator(sw);
generator.writeStartObject();
for (Map.Entry<String, String> entry : obj.map.entrySet()) {
generator.writeStringField(entry.getKey(), entry.getValue());
}
generator.writeEndObject();
generator.flush();
return new StringBody(sw.toString(), Charset.defaultCharset());
}
}
}

View File

@ -19,6 +19,7 @@
package org.mariotaku.twidere.api.twitter.model;
import com.bluelinelabs.logansquare.JsonMapper;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
@ -60,9 +61,12 @@ public class IDs extends TwitterResponseObject implements TwitterResponse, Curso
}
public static class Converter implements TypeConverter<IDs> {
private static final JsonMapper<IDs> IDS_JSON_MAPPER = LoganSquare.mapperFor(IDs.class);
@Override
public IDs parse(JsonParser jsonParser) throws IOException {
return LoganSquare.mapperFor(IDs.class).parse(jsonParser);
return IDS_JSON_MAPPER.parse(jsonParser);
}
@Override
@ -70,7 +74,7 @@ public class IDs extends TwitterResponseObject implements TwitterResponse, Curso
if (writeFieldNameForObject) {
jsonGenerator.writeFieldName(fieldName);
}
LoganSquare.mapperFor(IDs.class).serialize(object, jsonGenerator, true);
IDS_JSON_MAPPER.serialize(object, jsonGenerator, true);
}
}
}

View File

@ -42,7 +42,7 @@ public class ResponseCode {
return responseCode >= 200 && responseCode < 300;
}
public static class Converter implements RestConverter<HttpResponse, ResponseCode, TwitterException> {
public static class ResponseConverter implements RestConverter<HttpResponse, ResponseCode, TwitterException> {
@Override
public ResponseCode convert(HttpResponse response) {

View File

@ -3,16 +3,11 @@ package org.mariotaku.twidere.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import java.io.IOException;
import java.util.List;
@JsonObject
@ParcelablePlease
public class ParcelableMediaUpdate implements Parcelable {
@ -56,17 +51,6 @@ public class ParcelableMediaUpdate implements Parcelable {
return result;
}
@Deprecated
public static ParcelableMediaUpdate[] fromJSONString(final String json) {
if (TextUtils.isEmpty(json)) return null;
try {
final List<ParcelableMediaUpdate> list = LoganSquare.parseList(json, ParcelableMediaUpdate.class);
return list.toArray(new ParcelableMediaUpdate[list.size()]);
} catch (final IOException e) {
return null;
}
}
@Override
public int describeContents() {
return 0;

View File

@ -21,20 +21,14 @@ package org.mariotaku.twidere.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.UserMentionEntity;
import java.io.IOException;
import java.util.List;
@JsonObject
@ParcelablePlease(allFields = false)
public class ParcelableUserMention implements Parcelable {
@ -92,18 +86,6 @@ public class ParcelableUserMention implements Parcelable {
return true;
}
public static ParcelableUserMention[] fromSerializedJson(String string) {
if (string == null) return null;
final List<ParcelableUserMention> list;
try {
list = LoganSquare.parseList(string, ParcelableUserMention.class);
} catch (IOException e) {
return null;
}
if (list == null) return null;
return list.toArray(new ParcelableUserMention[list.size()]);
}
@Override
public int hashCode() {
final int prime = 31;
@ -126,21 +108,6 @@ public class ParcelableUserMention implements Parcelable {
dest.writeString(screen_name);
}
@Deprecated
public static ParcelableUserMention[] fromJSONString(final String json) {
if (TextUtils.isEmpty(json)) return null;
try {
final List<ParcelableUserMention> list = LoganSquare.parseList(json, ParcelableUserMention.class);
return list.toArray(new ParcelableUserMention[list.size()]);
} catch (final IOException e) {
return null;
}
}
public static ParcelableUserMention[] fromStatus(final Status status) {
return fromUserMentionEntities(status.getUserMentionEntities());
}
public static ParcelableUserMention[] fromUserMentionEntities(final UserMentionEntity[] entities) {
if (entities == null) return null;
final ParcelableUserMention[] mentions = new ParcelableUserMention[entities.length];
@ -150,21 +117,4 @@ public class ParcelableUserMention implements Parcelable {
return mentions;
}
public static boolean hasMention(final ParcelableUserMention[] mentions, final long id) {
if (mentions == null) return false;
for (final ParcelableUserMention mention : mentions) {
if (mention.id == id) return true;
}
return false;
}
public static boolean hasMention(final String json, final long id) {
final ParcelableUserMention[] mentions = fromJSONString(json);
if (mentions == null) return false;
for (final ParcelableUserMention mention : mentions) {
if (mention.id == id) return true;
}
return false;
}
}

View File

@ -23,9 +23,10 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.JsonMapper;
import org.mariotaku.library.objectcursor.converter.CursorFieldConverter;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.lang.reflect.Array;
@ -56,45 +57,68 @@ public class LoganSquareCursorFieldConverter implements CursorFieldConverter<Obj
}
}
private void writeObject(ContentValues values, Object object, String columnName, ParameterizedType fieldType) throws IOException {
private <T> void writeObject(ContentValues values, T object, String columnName, ParameterizedType fieldType) throws IOException {
if (object == null) return;
final Type rawType = fieldType.getRawType();
if (!(rawType instanceof Class)) throw new UnsupportedOperationException();
final Class rawCls = (Class) rawType;
if (List.class.isAssignableFrom(rawCls)) {
values.put(columnName, LoganSquare.serialize((List) object,
(Class) fieldType.getActualTypeArguments()[0]));
} else if (Map.class.isAssignableFrom(rawCls)) {
if (isArray(fieldType)) {
final Class<?> component = getArrayComponent(fieldType);
//noinspection unchecked
values.put(columnName, LoganSquare.serialize((Map) object,
(Class) fieldType.getActualTypeArguments()[1]));
} else if (rawCls.isArray()) {
final Class componentType = rawCls.getComponentType();
values.put(columnName, LoganSquare.serialize((List) Arrays.asList((Object[]) object),
componentType));
JsonMapper<Object> mapper = (JsonMapper<Object>) LoganSquareMapperFinder.mapperFor(component);
values.put(columnName, mapper.serialize(Arrays.asList((Object[]) object)));
} else if (fieldType.getRawType() == List.class) {
JsonMapper<Object> mapper = LoganSquareMapperFinder.mapperFor(fieldType.getActualTypeArguments()[0]);
//noinspection unchecked
values.put(columnName, mapper.serialize((List) object));
} else if (fieldType.getRawType() == Map.class) {
JsonMapper<Object> mapper = LoganSquareMapperFinder.mapperFor(fieldType.getActualTypeArguments()[1]);
//noinspection unchecked
values.put(columnName, mapper.serialize((Map) object));
} else {
values.put(columnName, LoganSquare.serialize(object));
JsonMapper<T> mapper = LoganSquareMapperFinder.mapperFor(fieldType);
values.put(columnName, mapper.serialize(object));
}
}
private Object getObject(Cursor cursor, int columnIndex, ParameterizedType fieldType) throws IOException {
final Type rawType = fieldType.getRawType();
if (!(rawType instanceof Class)) throw new UnsupportedOperationException();
final Class rawCls = (Class) rawType;
private <T> T getObject(Cursor cursor, int columnIndex, ParameterizedType fieldType) throws IOException {
final String string = cursor.getString(columnIndex);
if (TextUtils.isEmpty(string)) return null;
if (List.class.isAssignableFrom(rawCls)) {
// Parse list
return LoganSquare.parseList(string,
(Class) fieldType.getActualTypeArguments()[0]);
} else if (Map.class.isAssignableFrom(rawCls)) {
return LoganSquare.parseMap(string,
(Class) fieldType.getActualTypeArguments()[1]);
} else if (rawCls.isArray()) {
final Class componentType = rawCls.getComponentType();
List<?> list = LoganSquare.parseList(string, componentType);
return list.toArray((Object[]) Array.newInstance(componentType, list.size()));
if (isArray(fieldType)) {
final Class<?> component = getArrayComponent(fieldType);
//noinspection unchecked
JsonMapper<Object> mapper = (JsonMapper<Object>) LoganSquareMapperFinder.mapperFor(component);
final List<Object> list = mapper.parseList(string);
//noinspection unchecked
return (T) list.toArray((Object[]) Array.newInstance(component, list.size()));
} else if (fieldType.getRawType() == List.class) {
JsonMapper<Object> mapper = LoganSquareMapperFinder.mapperFor(fieldType.getActualTypeArguments()[0]);
//noinspection unchecked
return (T) mapper.parseList(string);
} else if (fieldType.getRawType() == Map.class) {
JsonMapper<Object> mapper = LoganSquareMapperFinder.mapperFor(fieldType.getActualTypeArguments()[1]);
//noinspection unchecked
return (T) mapper.parseMap(string);
} else {
JsonMapper<T> mapper = LoganSquareMapperFinder.mapperFor(fieldType);
return mapper.parse(string);
}
return LoganSquare.parse(string, rawCls);
}
private boolean isArray(Type type) {
if (type instanceof Class) {
return ((Class) type).isArray();
} else if (type instanceof ParameterizedType) {
return isArray(((ParameterizedType) type).getRawType());
}
return false;
}
private Class getArrayComponent(Type type) {
if (type instanceof Class) {
if (((Class) type).isArray()) {
return ((Class) type).getComponentType();
}
} else if (type instanceof ParameterizedType) {
return getArrayComponent(((ParameterizedType) type).getRawType());
}
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,76 @@
package org.mariotaku.twidere.util;
import com.bluelinelabs.logansquare.JsonMapper;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.ParameterizedType;
import com.bluelinelabs.logansquare.ParameterizedTypeAccessor;
import org.mariotaku.twidere.common.BuildConfig;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Created by mariotaku on 16/2/19.
*/
public class LoganSquareMapperFinder {
private static final ExecutorService pool = Executors.newSingleThreadExecutor();
public static <T> JsonMapper<T> mapperFor(Class<T> cls) throws ClassLoaderDeadLockException {
return mapperFor(ParameterizedTypeAccessor.<T>create(cls));
}
public static <T> JsonMapper<T> mapperFor(Type type) throws ClassLoaderDeadLockException {
return mapperFor(ParameterizedTypeAccessor.<T>create(type));
}
public static <T> JsonMapper<T> mapperFor(final ParameterizedType<T> type) throws ClassLoaderDeadLockException {
final Future<JsonMapper<T>> future = pool.submit(new Callable<JsonMapper<T>>() {
@Override
public JsonMapper<T> call() {
return LoganSquare.mapperFor(type);
}
});
final JsonMapper<T> mapper;
//noinspection TryWithIdenticalCatches
try {
mapper = future.get(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
if (BuildConfig.DEBUG) {
throw new RuntimeException(e);
}
BugReporter.logException(e);
throw new ClassLoaderDeadLockException(e);
}
return mapper;
}
public static class ClassLoaderDeadLockException extends IOException {
public ClassLoaderDeadLockException() {
super();
}
public ClassLoaderDeadLockException(String detailMessage) {
super(detailMessage);
}
public ClassLoaderDeadLockException(String message, Throwable cause) {
super(message, cause);
}
public ClassLoaderDeadLockException(Throwable cause) {
super(cause);
}
}
}

View File

@ -0,0 +1,100 @@
package org.mariotaku.twidere.model.util;
import android.content.ContentValues;
import android.database.MatrixCursor;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.junit.Test;
import org.mariotaku.twidere.util.JsonSerializer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
/**
* Created by mariotaku on 16/2/19.
*/
public class LoganSquareCursorFieldConverterTest {
private final LoganSquareCursorFieldConverter converter = new LoganSquareCursorFieldConverter();
private final Model jsonObject = new Model("a");
private final Model[] jsonArray = {new Model("a"), new Model("b"), new Model("c")};
private final List<Model> jsonList = Arrays.asList(jsonArray);
private final Map<String, Model> jsonMap = Collections.singletonMap("key", new Model("value"));
@Test
public void testParseField() throws Exception {
final String[] columns = {"json_object", "json_array", "json_list", "json_map"};
MatrixCursor cursor = new MatrixCursor(columns);
cursor.addRow(new String[]{
JsonSerializer.serialize(jsonObject, Model.class),
JsonSerializer.serialize(jsonArray, Model.class),
JsonSerializer.serialize(jsonList, Model.class),
JsonSerializer.serialize(jsonMap, Model.class)
});
cursor.moveToFirst();
assertEquals(jsonObject, converter.parseField(cursor, 0, TypeUtils.parameterize(Model.class)));
assertArrayEquals(jsonArray, (Model[]) converter.parseField(cursor, 1, TypeUtils.parameterize(Model[].class)));
assertEquals((Object) jsonList, converter.parseField(cursor, 2, TypeUtils.parameterize(List.class, Model.class)));
assertEquals((Object) jsonMap, converter.parseField(cursor, 3, TypeUtils.parameterize(Map.class, String.class, Model.class)));
}
@Test
public void testWriteField() throws Exception {
final ContentValues contentValues = new ContentValues();
converter.writeField(contentValues, jsonObject, "json_object", TypeUtils.parameterize(Model.class));
converter.writeField(contentValues, jsonArray, "json_array", TypeUtils.parameterize(Model[].class));
converter.writeField(contentValues, jsonList, "json_list", TypeUtils.parameterize(List.class, Model.class));
converter.writeField(contentValues, jsonMap, "json_map", TypeUtils.parameterize(Map.class, String.class, Model.class));
assertEquals(JsonSerializer.serialize(jsonObject, Model.class), contentValues.getAsString("json_object"));
assertEquals(JsonSerializer.serialize(jsonArray, Model.class), contentValues.getAsString("json_array"));
assertEquals(JsonSerializer.serialize(jsonList, Model.class), contentValues.getAsString("json_list"));
assertEquals(JsonSerializer.serialize(jsonMap, Model.class), contentValues.getAsString("json_map"));
}
@JsonObject
public static class Model {
@JsonField(name = "field")
String field;
public Model() {
}
public Model(String field) {
this.field = field;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Model model = (Model) o;
return !(field != null ? !field.equals(model.field) : model.field != null);
}
@Override
public int hashCode() {
return field != null ? field.hashCode() : 0;
}
}
}

View File

@ -22,12 +22,12 @@ package edu.tsinghua.hotmobi;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import com.bluelinelabs.logansquare.LoganSquare;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.Utils;
import java.io.IOException;
@ -89,7 +89,9 @@ public class WriteLogTask<T extends LogModel> implements Runnable, Constants {
Log.v(HotMobiLogger.LOGTAG, "Log " + type + ": " + event);
}
}
final byte[] bytes = LoganSquare.serialize(event).getBytes("UTF-8");
final String serialize = JsonSerializer.serialize(event);
if (TextUtils.isEmpty(serialize)) continue;
final byte[] bytes = serialize.getBytes("UTF-8");
final long start = raf.length();
final ByteBuffer bb;
if (start == 0) {

View File

@ -35,6 +35,7 @@ import org.mariotaku.twidere.model.ParcelableMediaUpdate;
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.MediaLoadingHandler;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
@ -69,7 +70,8 @@ public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
final DraftViewHolder holder = (DraftViewHolder) view.getTag();
final long[] accountIds = TwidereArrayUtils.parseLongArray(cursor.getString(mIndices.account_ids), ',');
final String text = cursor.getString(mIndices.text);
final ParcelableMediaUpdate[] mediaUpdates = ParcelableMediaUpdate.fromJSONString(cursor.getString(mIndices.media));
final ParcelableMediaUpdate[] mediaUpdates = JsonSerializer.parseArray(cursor.getString(mIndices.media),
ParcelableMediaUpdate.class);
final long timestamp = cursor.getLong(mIndices.timestamp);
final int actionType = cursor.getInt(mIndices.action_type);
final String actionName = getActionName(context, actionType);

View File

@ -35,6 +35,7 @@ import org.mariotaku.twidere.api.twitter.model.UserList;
import org.mariotaku.twidere.api.twitter.model.Warning;
import org.mariotaku.twidere.api.twitter.util.CRLFLineReader;
import org.mariotaku.twidere.api.twitter.util.JSONObjectType;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.io.InputStreamReader;
@ -71,11 +72,11 @@ public abstract class UserStreamCallback implements RawCallback {
break;
}
case STATUS: {
onStatus(LoganSquare.mapperFor(Status.class).parse(rootNode.traverse()));
onStatus(LoganSquareMapperFinder.mapperFor(Status.class).parse(rootNode.traverse()));
break;
}
case DIRECT_MESSAGE: {
onDirectMessage(LoganSquare.mapperFor(DirectMessage.class).parse(rootNode.traverse()));
onDirectMessage(LoganSquareMapperFinder.mapperFor(DirectMessage.class).parse(rootNode.traverse()));
break;
}
case DELETE: {
@ -146,7 +147,7 @@ public abstract class UserStreamCallback implements RawCallback {
private static <T> T parse(final Class<T> cls, final TreeNode json) throws IOException {
return LoganSquare.mapperFor(cls).parse(json.traverse());
return LoganSquareMapperFinder.mapperFor(cls).parse(json.traverse());
}
@Override

View File

@ -23,30 +23,20 @@ import android.support.annotation.NonNull;
import android.support.v4.util.SimpleArrayMap;
import com.bluelinelabs.logansquare.JsonMapper;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.ParameterizedType;
import com.bluelinelabs.logansquare.ParameterizedTypeAccessor;
import com.fasterxml.jackson.core.JsonParseException;
import org.mariotaku.restfu.RestConverter;
import org.mariotaku.restfu.http.HttpResponse;
import org.mariotaku.restfu.http.mime.Body;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
import org.mariotaku.twidere.api.twitter.model.CardDataMap;
import org.mariotaku.twidere.api.twitter.model.ResponseCode;
import org.mariotaku.twidere.api.twitter.model.TwitterResponse;
import org.mariotaku.twidere.util.BugReporter;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Created by mariotaku on 15/5/5.
@ -56,11 +46,12 @@ public class TwitterConverterFactory extends RestConverter.SimpleFactory<Twitter
private static SimpleArrayMap<Type, RestConverter<HttpResponse, ?, TwitterException>> sResponseConverters = new SimpleArrayMap<>();
private static SimpleArrayMap<Type, RestConverter<?, Body, TwitterException>> sBodyConverters = new SimpleArrayMap<>();
private static final ExecutorService pool = Executors.newSingleThreadExecutor();
static {
sResponseConverters.put(ResponseCode.class, new ResponseCode.Converter());
sResponseConverters.put(OAuthToken.class, new OAuthToken.Converter());
sResponseConverters.put(ResponseCode.class, new ResponseCode.ResponseConverter());
sResponseConverters.put(OAuthToken.class, new OAuthToken.ResponseConverter());
// sBodyConverters.put(CardDataMap.class, new CardDataMap.BodyConverter());
}
@NonNull
@ -83,35 +74,11 @@ public class TwitterConverterFactory extends RestConverter.SimpleFactory<Twitter
if (converter != null) {
return converter;
}
final ParameterizedType<?> parameterizedType = ParameterizedTypeAccessor.create(type);
final Future<JsonMapper<?>> future = pool.submit(new Callable<JsonMapper<?>>() {
@Override
public JsonMapper<?> call() {
return LoganSquare.mapperFor(parameterizedType);
}
});
final JsonMapper<?> mapper;
//noinspection TryWithIdenticalCatches
try {
mapper = future.get(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
final Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw ((RuntimeException) cause);
} else if (cause instanceof Error) {
throw ((Error) cause);
} else {
throw new RuntimeException(e);
}
} catch (TimeoutException e) {
if (BuildConfig.DEBUG) {
throw new RuntimeException(e);
} else {
BugReporter.logException(e);
throw new RestConverter.ConvertException(e);
}
mapper = LoganSquareMapperFinder.mapperFor(type);
} catch (LoganSquareMapperFinder.ClassLoaderDeadLockException e) {
throw new RestConverter.ConvertException(e);
}
return new JsonConverter(mapper);
}

View File

@ -68,6 +68,7 @@ import org.mariotaku.twidere.model.util.ParcelableStatusUpdateUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.ThemeUtils;
import java.io.File;
@ -328,10 +329,12 @@ public class DraftsFragment extends BaseSupportFragment implements Constants, Lo
final Expression where = Expression.in(new Column(Drafts._ID), new RawItemArray(mIds));
final String[] projection = {Drafts.MEDIA};
final Cursor c = resolver.query(Drafts.CONTENT_URI, projection, where.getSQL(), null, null);
if (c == null) return 0;
final int idxMedia = c.getColumnIndex(Drafts.MEDIA);
c.moveToFirst();
while (!c.isAfterLast()) {
final ParcelableMediaUpdate[] mediaArray = ParcelableMediaUpdate.fromJSONString(c.getString(idxMedia));
final ParcelableMediaUpdate[] mediaArray = JsonSerializer.parseArray(c.getString(idxMedia),
ParcelableMediaUpdate.class);
if (mediaArray != null) {
for (final ParcelableMediaUpdate media : mediaArray) {
final Uri uri = Uri.parse(media.uri);

View File

@ -26,10 +26,11 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nostra13.universalimageloader.cache.disc.DiskCache;
import com.nostra13.universalimageloader.utils.IoUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.Paging;
@ -39,6 +40,7 @@ import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
@ -52,7 +54,11 @@ import java.io.PipedOutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.inject.Inject;
@ -208,12 +214,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
if (key == null) return null;
final File file = mFileCache.get(key);
if (file == null) return null;
try {
return JsonSerializer.parseList(file, ParcelableStatus.class);
} catch (final IOException e) {
// Ignore
}
return null;
return JsonSerializer.parseList(file, ParcelableStatus.class);
}
private String getSerializationKey() {
@ -221,6 +222,8 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
return TwidereArrayUtils.toString(mSavedStatusesFileArgs, '_', false);
}
private static final ExecutorService pool = Executors.newSingleThreadExecutor();
private void saveCachedData(final List<ParcelableStatus> data) {
final String key = getSerializationKey();
if (key == null || data == null) return;
@ -229,19 +232,27 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
final List<ParcelableStatus> statuses = data.subList(0, Math.min(databaseItemLimit, data.size()));
final PipedOutputStream pos = new PipedOutputStream();
final PipedInputStream pis = new PipedInputStream(pos);
new Thread(new Runnable() {
final Future<Object> future = pool.submit(new Callable<Object>() {
@Override
public void run() {
try {
LoganSquare.mapperFor(ParcelableStatus.class).serialize(statuses, pos);
} catch (IOException e) {
e.printStackTrace();
}
public Object call() throws Exception {
LoganSquareMapperFinder.mapperFor(ParcelableStatus.class).serialize(statuses, pos);
return null;
}
}).start();
mFileCache.save(key, pis, null);
} catch (final IOException e) {
});
final boolean saved = mFileCache.save(key, pis, new IoUtils.CopyListener() {
@Override
public boolean onBytesCopied(int current, int total) {
return !future.isDone();
}
});
if (BuildConfig.DEBUG) {
Log.v(LOGTAG, key + " saved: " + saved);
}
} catch (final Exception e) {
// Ignore
if (BuildConfig.DEBUG && !(e instanceof IOException)) {
Log.w(LOGTAG, e);
}
}
}

View File

@ -22,8 +22,6 @@ package org.mariotaku.twidere.util;
import android.content.ContentValues;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.LoganSquare;
import org.json.JSONException;
import org.json.JSONObject;
import org.mariotaku.twidere.TwidereConstants;
@ -63,7 +61,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -185,10 +182,8 @@ public final class ContentValuesCreator implements TwidereConstants {
values.put(DirectMessages.SENDER_PROFILE_IMAGE_URL, sender_profile_image_url);
values.put(DirectMessages.RECIPIENT_PROFILE_IMAGE_URL, recipient_profile_image_url);
final ParcelableMedia[] mediaArray = ParcelableMediaUtils.fromEntities(message);
try {
values.put(DirectMessages.MEDIA_JSON, LoganSquare.serialize(Arrays.asList(mediaArray), ParcelableMedia.class));
} catch (IOException ignored) {
}
values.put(DirectMessages.MEDIA_JSON, JsonSerializer.serialize(Arrays.asList(mediaArray),
ParcelableMedia.class));
return values;
}
@ -235,10 +230,8 @@ public final class ContentValuesCreator implements TwidereConstants {
values.put(Drafts.TIMESTAMP, System.currentTimeMillis());
if (imageUri != null) {
final ParcelableMediaUpdate[] mediaArray = {new ParcelableMediaUpdate(imageUri, 0)};
try {
values.put(Drafts.MEDIA, LoganSquare.serialize(Arrays.asList(mediaArray), ParcelableMediaUpdate.class));
} catch (IOException ignored) {
}
values.put(Drafts.MEDIA, JsonSerializer.serialize(Arrays.asList(mediaArray),
ParcelableMediaUpdate.class));
}
final JSONObject extras = new JSONObject();
try {

View File

@ -21,13 +21,15 @@ package org.mariotaku.twidere.util;
import android.support.annotation.Nullable;
import com.bluelinelabs.logansquare.LoganSquare;
import com.bluelinelabs.logansquare.JsonMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* Created by mariotaku on 15/8/6.
@ -38,7 +40,27 @@ public class JsonSerializer {
public static <T> String serialize(@Nullable final List<T> list, final Class<T> cls) {
if (list == null) return null;
try {
return LoganSquare.serialize(list, cls);
return LoganSquareMapperFinder.mapperFor(cls).serialize(list);
} catch (IOException e) {
return null;
}
}
@Nullable
public static <T> String serialize(@Nullable final Map<String, T> list, final Class<T> cls) {
if (list == null) return null;
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(list);
} catch (IOException e) {
return null;
}
}
@Nullable
public static <T> String serialize(@Nullable final T[] array, final Class<T> cls) {
if (array == null) return null;
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(Arrays.asList(array));
} catch (IOException e) {
return null;
}
@ -48,7 +70,20 @@ public class JsonSerializer {
public static <T> String serialize(@Nullable final T object, final Class<T> cls) {
if (object == null) return null;
try {
return LoganSquare.mapperFor(cls).serialize(object);
return LoganSquareMapperFinder.mapperFor(cls).serialize(object);
} catch (IOException e) {
return null;
}
}
@Nullable
public static <T> String serialize(@Nullable final T object) {
if (object == null) return null;
try {
//noinspection unchecked
final JsonMapper<T> mapper = (JsonMapper<T>)
LoganSquareMapperFinder.mapperFor(object.getClass());
return mapper.serialize(object);
} catch (IOException e) {
return null;
}
@ -58,7 +93,7 @@ public class JsonSerializer {
public static <T> T[] parseArray(@Nullable final String string, final Class<T> cls) {
if (string == null) return null;
try {
final List<T> list = LoganSquare.mapperFor(cls).parseList(string);
final List<T> list = LoganSquareMapperFinder.mapperFor(cls).parseList(string);
//noinspection unchecked
return list.toArray((T[]) Array.newInstance(cls, list.size()));
} catch (IOException e) {
@ -70,26 +105,22 @@ public class JsonSerializer {
public static <T> T parse(@Nullable final String string, final Class<T> cls) {
if (string == null) return null;
try {
return LoganSquare.mapperFor(cls).parse(string);
return LoganSquareMapperFinder.mapperFor(cls).parse(string);
} catch (IOException e) {
return null;
}
}
@Nullable
public static <T> String serialize(@Nullable final T obj) {
if (obj == null) return null;
//noinspection unchecked
return serialize(obj, (Class<T>) obj.getClass());
}
public static <E> List<E> parseList(File file, Class<E> jsonObjectClass) throws IOException {
final FileInputStream is = new FileInputStream(file);
public static <E> List<E> parseList(File file, Class<E> cls) {
FileInputStream is = null;
//noinspection TryFinallyCanBeTryWithResources
try {
return LoganSquare.parseList(is, jsonObjectClass);
is = new FileInputStream(file);
return LoganSquareMapperFinder.mapperFor(cls).parseList(is);
} catch (IOException e) {
return null;
} finally {
is.close();
Utils.closeSilently(is);
}
}

View File

@ -109,8 +109,6 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.bluelinelabs.logansquare.LoganSquare;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.json.JSONException;
@ -292,10 +290,11 @@ public final class Utils implements Constants {
throw new AssertionError("You are trying to create an instance for this utility class!");
}
public static void addIntentToMenuForExtension(final Context context, final Menu menu, final int groupId,
final String action, final String parelableKey, final String parelableJSONKey,
public static void addIntentToMenuForExtension(final Context context, final Menu menu,
final int groupId, final String action,
final String parcelableKey, final String parcelableJSONKey,
final Parcelable parcelable) {
if (context == null || menu == null || action == null || parelableKey == null || parcelable == null)
if (context == null || menu == null || action == null || parcelableKey == null || parcelable == null)
return;
final PackageManager pm = context.getPackageManager();
final Resources res = context.getResources();
@ -304,18 +303,13 @@ public final class Utils implements Constants {
final Intent queryIntent = new Intent(action);
queryIntent.setExtrasClassLoader(context.getClassLoader());
final List<ResolveInfo> activities = pm.queryIntentActivities(queryIntent, PackageManager.GET_META_DATA);
String parcelableJson = null;
try {
parcelableJson = LoganSquare.serialize(parcelable);
} catch (IOException ignored) {
}
final String parcelableJson = JsonSerializer.serialize(parcelable);
for (final ResolveInfo info : activities) {
final Intent intent = new Intent(queryIntent);
if (isExtensionUseJSON(info) && parcelableJson != null) {
intent.putExtra(parelableJSONKey, parcelableJson);
intent.putExtra(parcelableJSONKey, parcelableJson);
} else {
intent.putExtra(parelableKey, parcelable);
intent.putExtra(parcelableKey, parcelable);
}
intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
final MenuItem item = menu.add(groupId, Menu.NONE, Menu.NONE, info.loadLabel(pm));