After following Support Caching in Apollo Android here: Support For Cached Responses for Android
And already tried to query offline and it works fine and data is coming from the cache
First scenario after opening the app is loading the list of Data using Query from "MyApolloClient" object which is a custom class inherit from "ApolloClient"
After getting the data using ".watcher().enqueueAndWatch()" method to callback response from Apollo with new data and update the recyclerView
I select item to update or "Mutate" a record from the query data list to change it in cache and database of course.
I can click on any item and then it show a dialog to edit name of that record item
After sending the updated name using Mutation
normally, the cache changed and the database online changed too.
The problem here: the UI doesn't changed at all because .watcher()
method which returns instance of ApolloQueryWatcher
who has a method called enqueueAndWatch
doesn't trigger as a listener to any changes to update UI and the list with the new changed value of that record
Here are some snippets from my Code, I am using Kotlin and Java.
The Method to get data of users from database using Query
fun getAllUsers() { progress.visibility = VISIBLE MyApolloClient.getApolloClient(this).query(GetUsersWithPagesQuery.builder().build()) .watcher().enqueueAndWatch(object : MyApolloClient.MyCallBack<GetUsersWithPagesQuery.Data>(this) { override fun onResponseUI(response: Response<GetUsersWithPagesQuery.Data>) { progress.visibility = GONE if (response.data() != null) { reachBottom = false users.clear() for (i in response.data()!!.users()) { val u = GetUsersWithPagesQuery.Data1("", i.id(), i.name(), i.email()) users.add(u) } adapter.notifyDataSetChanged() } } override fun onFailureUI(response: ApolloException) { } })
}
Custom Callback to use response in UI
public static abstract class MyCallBack<T> extends ApolloCall.Callback<T> { Activity activity; public MyCallBack(Activity activity) { this.activity = activity; } @Override public void onResponse(@NotNull com.apollographql.apollo.api.Response<T> response) { activity.runOnUiThread(() -> onResponseUI(response)); } public abstract void onResponseUI(@NotNull com.apollographql.apollo.api.Response<T> response); public abstract void onFailureUI(@NotNull ApolloException response); @Override public void onFailure(@NotNull ApolloException e) { activity.runOnUiThread(() -> onFailureUI(e)); }
}
getting object of Apollo Client with Caching support
public static ApolloClient getApolloClient(Context context) { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addNetworkInterceptor(httpLoggingInterceptor); builder.addNetworkInterceptor(chain -> { Request original = chain.request(); Request.Builder builder1 = original.newBuilder().method(original.method(), original.body()); builder1.header("Authorization", "Bearer " + PrefManager.getInstance(context).getAPIToken()); return chain.proceed(builder1.build()); }); OkHttpClient okHttpClient = builder.build(); //Directory where cached responses will be stored File file = new File(context.getApplicationContext().getFilesDir(), "apolloCache"); //Size in bytes of the cache long size = 1024 * 1024; //Create the http response cache store DiskLruHttpCacheStore cacheStore = new DiskLruHttpCacheStore(file, size); ApolloSqlHelper apolloSqlHelper = ApolloSqlHelper.create(context, "zari"); //Create NormalizedCacheFactory NormalizedCacheFactory cacheFactory = new SqlNormalizedCacheFactory(apolloSqlHelper); //Create the cache key resolver, this example works well when all types have globally unique ids. CacheKeyResolver resolver = new CacheKeyResolver() { @NotNull @Override public CacheKey fromFieldRecordSet(@NotNull ResponseField field, @NotNull Map<String, Object> recordSet) { return formatCacheKey((String) recordSet.get("id")); } @NotNull @Override public CacheKey fromFieldArguments(@NotNull ResponseField field, @NotNull Operation.Variables variables) { return formatCacheKey((String) field.resolveArgument("id", variables)); } private CacheKey formatCacheKey(String id) { if (id == null || id.isEmpty()) { return CacheKey.NO_KEY; } else { return CacheKey.from(id); } } }; apolloClient = ApolloClient.builder() .serverUrl(url) //.httpCache(new ApolloHttpCache(cacheStore)) .normalizedCache(cacheFactory, resolver) .okHttpClient(okHttpClient) .build(); return apolloClient;
}
alert dialog with edit text to update item from list in Recycler Adapter
builder.setPositiveButton("Change", (dialog, which) -> { if (!n.isEmpty()) MyApolloClient.getApolloClient(activity).mutate(UpdateUserMutation.builder().id(user .id()).name(n).build()).enqueue(new MyApolloClient.MyCallBack<UpdateUserMutation.Data>(activity) { @Override public void onResponseUI(@NotNull Response<UpdateUserMutation.Data> response) { if (response.errors() != null && response.errors().size() > 0) { StaticMembers.toastMessageShort(activity, response.errors().get(0).message()); } else { StaticMembers.toastMessageShort(activity, response.data().updateUser().name() + " updated"); } } @Override public void onFailureUI(@NotNull ApolloException response) { } }); });
So, Can anyone please help?