Initial replacement of Gson by Moshi

Replace GsonConverterFactory by MoshiConverterFactory and create feed adapter for FreshRSS feeds api call
This commit is contained in:
Shinokuni 2020-01-03 14:25:51 +01:00
parent 6c62f7c9a8
commit 0b68bf6c51
9 changed files with 130 additions and 47 deletions

View File

@ -7,21 +7,19 @@ import android.util.TimingLogger;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils;
import com.readrops.app.utils.matchers.ItemMatcher;
import com.readrops.readropsdb.entities.Feed; import com.readrops.readropsdb.entities.Feed;
import com.readrops.readropsdb.entities.Folder; import com.readrops.readropsdb.entities.Folder;
import com.readrops.readropsdb.entities.Item; import com.readrops.readropsdb.entities.Item;
import com.readrops.readropsdb.entities.account.Account; import com.readrops.readropsdb.entities.account.Account;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.matchers.FeedMatcher;
import com.readrops.app.utils.matchers.ItemMatcher;
import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils;
import com.readrops.readropslibrary.services.Credentials; import com.readrops.readropslibrary.services.Credentials;
import com.readrops.readropslibrary.services.SyncType; import com.readrops.readropslibrary.services.SyncType;
import com.readrops.readropslibrary.services.freshrss.FreshRSSAPI; import com.readrops.readropslibrary.services.freshrss.FreshRSSAPI;
import com.readrops.readropslibrary.services.freshrss.FreshRSSCredentials; import com.readrops.readropslibrary.services.freshrss.FreshRSSCredentials;
import com.readrops.readropslibrary.services.freshrss.FreshRSSSyncData; import com.readrops.readropslibrary.services.freshrss.FreshRSSSyncData;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFeed;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolder; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolder;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItem; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItem;
@ -192,14 +190,8 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
.andThen(super.deleteFolder(folder)); .andThen(super.deleteFolder(folder));
} }
private void insertFeeds(List<FreshRSSFeed> freshRSSFeeds) { private void insertFeeds(List<Feed> freshRSSFeeds) {
List<Feed> feeds = new ArrayList<>(); List<Long> insertedFeedsIds = database.feedDao().feedsUpsert(freshRSSFeeds, account);
for (FreshRSSFeed freshRSSFeed : freshRSSFeeds) {
feeds.add(FeedMatcher.freshRSSFeedToFeed(freshRSSFeed, account));
}
List<Long> insertedFeedsIds = database.feedDao().feedsUpsert(feeds, account);
if (!insertedFeedsIds.isEmpty()) { if (!insertedFeedsIds.isEmpty()) {
setFeedsColors(database.feedDao().selectFromIdList(insertedFeedsIds)); setFeedsColors(database.feedDao().selectFromIdList(insertedFeedsIds));

View File

@ -1,6 +1,7 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion rootProject.ext.compileSdkVersion compileSdkVersion rootProject.ext.compileSdkVersion
@ -34,17 +35,24 @@ dependencies {
implementation project(':readropsdb') implementation project(':readropsdb')
implementation "androidx.core:core-ktx:1.1.0" implementation "androidx.core:core-ktx:1.1.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.squareup.retrofit2:retrofit:2.6.1' implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1' implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
implementation 'com.squareup.retrofit2:converter-simplexml:2.6.1' implementation('com.squareup.retrofit2:converter-moshi:2.7.1') {
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1' exclude group: 'moshi', module: 'moshi' // moshi converter uses moshi 1.8.0 which breaks codegen 1.9.2
}
implementation 'com.squareup.retrofit2:converter-simplexml:2.7.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1'
implementation 'com.squareup.moshi:moshi:1.9.2'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.9.2'
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.2.0'

View File

@ -3,10 +3,11 @@ package com.readrops.readropslibrary.services;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.readrops.readropslibrary.utils.HttpManager; import com.readrops.readropslibrary.utils.HttpManager;
import com.squareup.moshi.Moshi;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.moshi.MoshiConverterFactory;
/** /**
* Abstraction level for services APIs * Abstraction level for services APIs
@ -23,10 +24,12 @@ public abstract class API<T> {
api = createAPI(credentials, clazz, endPoint); api = createAPI(credentials, clazz, endPoint);
} }
protected abstract Moshi buildMoshi();
protected Retrofit getConfiguredRetrofitInstance(@NonNull String endPoint) { protected Retrofit getConfiguredRetrofitInstance(@NonNull String endPoint) {
return new Retrofit.Builder() return new Retrofit.Builder()
.baseUrl(HttpManager.getInstance().getCredentials().getUrl() + endPoint) .baseUrl(HttpManager.getInstance().getCredentials().getUrl() + endPoint)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(MoshiConverterFactory.create(buildMoshi()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(HttpManager.getInstance().getOkHttpClient()) .client(HttpManager.getInstance().getOkHttpClient())
.build(); .build();

View File

@ -3,13 +3,15 @@ package com.readrops.readropslibrary.services.freshrss;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.readrops.readropsdb.entities.Feed;
import com.readrops.readropslibrary.services.API; import com.readrops.readropslibrary.services.API;
import com.readrops.readropslibrary.services.Credentials; import com.readrops.readropslibrary.services.Credentials;
import com.readrops.readropslibrary.services.SyncType; import com.readrops.readropslibrary.services.SyncType;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFeeds; import com.readrops.readropslibrary.services.freshrss.adapters.FreshRSSFeedAdapter;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolders; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolders;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItems; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItems;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSUserInfo; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSUserInfo;
import com.squareup.moshi.Moshi;
import java.io.StringReader; import java.io.StringReader;
import java.util.List; import java.util.List;
@ -30,6 +32,13 @@ public class FreshRSSAPI extends API<FreshRSSService> {
super(credentials, FreshRSSService.class, FreshRSSService.END_POINT); super(credentials, FreshRSSService.class, FreshRSSService.END_POINT);
} }
@Override
protected Moshi buildMoshi() {
return new Moshi.Builder()
.add(new FreshRSSFeedAdapter())
.build();
}
/** /**
* Call token API to generate a new token from account credentials * Call token API to generate a new token from account credentials
* *
@ -83,7 +92,7 @@ public class FreshRSSAPI extends API<FreshRSSService> {
public Single<FreshRSSSyncResult> sync(@NonNull SyncType syncType, @NonNull FreshRSSSyncData syncData, @NonNull String writeToken) { public Single<FreshRSSSyncResult> sync(@NonNull SyncType syncType, @NonNull FreshRSSSyncData syncData, @NonNull String writeToken) {
FreshRSSSyncResult syncResult = new FreshRSSSyncResult(); FreshRSSSyncResult syncResult = new FreshRSSSyncResult();
return setItemsReadState(syncData, writeToken) /*return setItemsReadState(syncData, writeToken)
.andThen(getFolders() .andThen(getFolders()
.flatMap(freshRSSFolders -> { .flatMap(freshRSSFolders -> {
syncResult.setFolders(freshRSSFolders.getTags()); syncResult.setFolders(freshRSSFolders.getTags());
@ -107,7 +116,14 @@ public class FreshRSSAPI extends API<FreshRSSService> {
syncResult.setLastUpdated(freshRSSItems.getUpdated()); syncResult.setLastUpdated(freshRSSItems.getUpdated());
return Single.just(syncResult); return Single.just(syncResult);
})); }));*/
return getFeeds()
.flatMap(freshRSSFeeds -> {
syncResult.setFeeds(freshRSSFeeds);
return Single.just(syncResult);
});
} }
/** /**
@ -124,7 +140,7 @@ public class FreshRSSAPI extends API<FreshRSSService> {
* *
* @return the feeds * @return the feeds
*/ */
public Single<FreshRSSFeeds> getFeeds() { public Single<List<Feed>> getFeeds() {
return api.getFeeds(); return api.getFeeds();
} }

View File

@ -1,6 +1,6 @@
package com.readrops.readropslibrary.services.freshrss; package com.readrops.readropslibrary.services.freshrss;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFeeds; import com.readrops.readropsdb.entities.Feed;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolders; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolders;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItems; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItems;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSUserInfo; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSUserInfo;
@ -32,7 +32,7 @@ public interface FreshRSSService {
Single<FreshRSSUserInfo> getUserInfo(); Single<FreshRSSUserInfo> getUserInfo();
@GET("reader/api/0/subscription/list?output=json") @GET("reader/api/0/subscription/list?output=json")
Single<FreshRSSFeeds> getFeeds(); Single<List<Feed>> getFeeds();
@GET("reader/api/0/stream/contents/user/-/state/com.google/reading-list") @GET("reader/api/0/stream/contents/user/-/state/com.google/reading-list")
Single<FreshRSSItems> getItems(@Query("xt") String excludeTarget, @Query("n") int max, @Query("ot") Long lastModified); Single<FreshRSSItems> getItems(@Query("xt") String excludeTarget, @Query("n") int max, @Query("ot") Long lastModified);

View File

@ -1,6 +1,6 @@
package com.readrops.readropslibrary.services.freshrss; package com.readrops.readropslibrary.services.freshrss;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFeed; import com.readrops.readropsdb.entities.Feed;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolder; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSFolder;
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItem; import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItem;
@ -11,7 +11,7 @@ public class FreshRSSSyncResult {
private List<FreshRSSFolder> folders; private List<FreshRSSFolder> folders;
private List<FreshRSSFeed> feeds; private List<Feed> feeds;
private List<FreshRSSItem> items; private List<FreshRSSItem> items;
@ -22,11 +22,11 @@ public class FreshRSSSyncResult {
items = new ArrayList<>(); items = new ArrayList<>();
} }
public List<FreshRSSFeed> getFeeds() { public List<Feed> getFeeds() {
return feeds; return feeds;
} }
public void setFeeds(List<FreshRSSFeed> feeds) { public void setFeeds(List<Feed> feeds) {
this.feeds = feeds; this.feeds = feeds;
} }

View File

@ -0,0 +1,73 @@
package com.readrops.readropslibrary.services.freshrss.adapters
import android.annotation.SuppressLint
import com.readrops.readropsdb.entities.Feed
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonReader
import com.squareup.moshi.ToJson
class FreshRSSFeedAdapter {
@ToJson
fun toJson(feed: Feed): String = ""
@SuppressLint("CheckResult")
@FromJson
fun fromJson(reader: JsonReader): List<Feed> {
val feeds = mutableListOf<Feed>()
reader.beginObject()
reader.nextName() // "subscriptions", beginning of the feed array
reader.beginArray()
while (reader.hasNext()) {
reader.beginObject()
val feed = Feed()
while (reader.hasNext()) {
with(feed) {
when (reader.nextName()) {
"title" -> name = reader.nextString()
"url" -> url = reader.nextString()
"htmlUrl" -> siteUrl = reader.nextString()
"iconUrl" -> iconUrl = reader.nextString()
"id" -> remoteId = reader.nextString()
"categories" -> remoteFolderId = getCategoryId(reader)
else -> reader.skipValue()
}
}
}
feeds += feed
reader.endObject()
}
reader.endArray()
reader.endObject()
return feeds
}
private fun getCategoryId(reader: JsonReader): String? {
var id: String? = null
reader.beginArray()
while (reader.hasNext()) {
reader.beginObject()
while (reader.hasNext()) {
when (reader.nextName()) {
"id" -> id = reader.nextString()
else -> reader.skipValue()
}
}
reader.endObject()
if (!id.isNullOrEmpty())
break
}
reader.endArray()
return id
}
}

View File

@ -1,16 +0,0 @@
package com.readrops.readropslibrary.services.freshrss.json;
import java.util.List;
public class FreshRSSFeeds {
private List<FreshRSSFeed> subscriptions;
public List<FreshRSSFeed> getSubscriptions() {
return subscriptions;
}
public void setSubscriptions(List<FreshRSSFeed> subscriptions) {
this.subscriptions = subscriptions;
}
}

View File

@ -19,6 +19,7 @@ import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser;
import com.readrops.readropslibrary.utils.ConflictException; import com.readrops.readropslibrary.utils.ConflictException;
import com.readrops.readropslibrary.utils.LibUtils; import com.readrops.readropslibrary.utils.LibUtils;
import com.readrops.readropslibrary.utils.UnknownFormatException; import com.readrops.readropslibrary.utils.UnknownFormatException;
import com.squareup.moshi.Moshi;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -34,6 +35,12 @@ public class NextNewsAPI extends API<NextNewsService> {
super(credentials, NextNewsService.class, NextNewsService.END_POINT); super(credentials, NextNewsService.class, NextNewsService.END_POINT);
} }
@Override
protected Moshi buildMoshi() {
return new Moshi.Builder()
.build();
}
public NextNewsUser login() throws IOException { public NextNewsUser login() throws IOException {
Response<NextNewsUser> response = api.getUser().execute(); Response<NextNewsUser> response = api.getUser().execute();