i’m working on a chat app , i’m trying to load messages from cache first then network using the CACHE_THEN_NETWORK policy
but somehow it’s not always loading from network
like if i return to chats fragment that contains chats with different people then return to the chat i was inside and run the same query …
last messages aren’t listed … i have to exit then reenter to make them listed
so i did a tweak which is bad for user experience and i need a good solution or more details about this cache policy
my messaging class
package com.a2r.dwarup;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.a2r.dwarup.Adapters.MessagesRecyclerViewAdapter;
import com.a2r.dwarup.Model.Message;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.parse.FindCallback;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.livequery.ParseLiveQueryClient;
import com.parse.livequery.SubscriptionHandling;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class MessagesActivity extends AppCompatActivity {
private static final String TAG = "TAG";
RecyclerView recyclerView;
TextInputEditText messageboard;
String title,chatid;
ImageView profilepic;
MaterialButton moreinfos ;
LinearLayoutManager linearLayoutManager;
private final List<Message> messagesList = new ArrayList<>();
MessagesRecyclerViewAdapter messageAdapter ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messages);
if(savedInstanceState!=null){
Log.i(TAG, "onCreate: not null");
}
moreinfos = new MaterialButton(this,null,R.style.Theme_DwaRup);
//getting chat title and id
title = getIntent().getStringExtra("title");
chatid = getIntent().getStringExtra("chatid");
MaterialToolbar toolbar = findViewById(R.id.toolbar);
this.setSupportActionBar(toolbar);
this.getSupportActionBar().setTitle(title);
messageboard = findViewById(R.id.messageboard);
profilepic = new ImageView(this);
recyclerView = findViewById(R.id.messagesrecycler);
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(linearLayoutManager);
linearLayoutManager.setStackFromEnd(true);
messageAdapter = new MessagesRecyclerViewAdapter(this,messagesList, MainActivity.uid);
recyclerView.setAdapter(messageAdapter);
recyclerView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
if(bottom<oldBottom) {
recyclerView.post(() -> recyclerView.scrollToPosition(0));
}
});
recyclerView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.i("TAG", "onScrollChange: ");
if(linearLayoutManager.findFirstCompletelyVisibleItemPosition()==messagesList.size()){
loadmoremessages(messagesList.get(messagesList.size()-1).getTimestamp());
}
}
});
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "Resume: size is "+messagesList.size()+"hash "+this.hashCode());
loadMessages(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
listenForNewMessages();
}
ParseLiveQueryClient parseLiveQueryClient = null;
@SuppressWarnings("rawtypes") ParseQuery livechat = ParseQuery.getQuery("Messages");
public void listenForNewMessages(){
//Listening for new messages to come
parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient();
/*
try {
parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient(new URI("wss://dwarup.b4a.io/"));
} catch (URISyntaxException e) {
e.printStackTrace();
}*/
livechat.whereEqualTo("chatid",chatid);
livechat.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ONLY);
SubscriptionHandling<ParseObject> subscriptionHandling = parseLiveQueryClient.subscribe(livechat);
subscriptionHandling.handleEvent( SubscriptionHandling.Event.CREATE, new SubscriptionHandling.HandleEventCallback<ParseObject>(){
ParseLiveQueryClient parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient();
@Override
public void onEvent(ParseQuery<ParseObject> query, ParseObject object) {
// HANDLING create event
Message msg = new Message(object.getString("owner"),object.getString("content"),object.getLong("timestamp"),object.getString("state"));
messagesList.add(0,msg);
MessagesActivity.this.runOnUiThread(() -> {
messageAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(0);
});
//i check if new message is his so that i turn it to seen on server
if(!msg.getOwner().equals(MainActivity.uid)){
object.put("state","seen");
object.saveInBackground();
}else{
@SuppressWarnings("rawtypes") ParseQuery livemsg = ParseQuery.getQuery("Messages");
livemsg.whereEqualTo("chatid",chatid);
SubscriptionHandling<ParseObject> msgsubscriptionHandling = parseLiveQueryClient.subscribe(livemsg);
msgsubscriptionHandling.handleEvent(SubscriptionHandling.Event.UPDATE, new SubscriptionHandling.HandleEventCallback<ParseObject>() {
@Override
public void onEvent(ParseQuery<ParseObject> query, ParseObject object) {
//searching for msg
for (Message msg : messagesList
) {
if(msg.getTimestamp()==object.getLong("timestamp")&&msg.getOwner().equals(MainActivity.uid)){
msg.setState("seen");
MessagesActivity.this.runOnUiThread(() -> {
messageAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(0);
});
parseLiveQueryClient.unsubscribe(livemsg);
break;
}
}
}
});
}
}});
}
public void loadmoremessages(long timestamp){
ParseQuery localMessagesQuery = ParseQuery.getQuery("Messages");
localMessagesQuery.whereEqualTo("chatid", chatid);
localMessagesQuery.orderByDescending("timestamp");
localMessagesQuery.whereLessThan("timestamp",timestamp);
localMessagesQuery.setCachePolicy(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
localMessagesQuery.setLimit(15);
localMessagesQuery.findInBackground((FindCallback<ParseObject>) (msgsList, e) -> {
if (e == null) {
Log.d("msgs", "Retrieved " + msgsList.size() + " msg from cache");
for (ParseObject msg : msgsList
) {
Message message = new Message(msg.getString("owner"), msg.getString("content"), msg.getLong("timestamp"), msg.getString("state"));
messagesList.add(message);
messageAdapter.notifyDataSetChanged();
recyclerView.scrollToPosition(0);
}
}
});
}
public void loadMessages(ParseQuery.CachePolicy cachePolicy) {
ParseQuery localMessagesQuery = ParseQuery.getQuery("Messages");
localMessagesQuery.whereEqualTo("chatid", chatid);
localMessagesQuery.orderByDescending("timestamp");
localMessagesQuery.setCachePolicy(cachePolicy);
localMessagesQuery.setLimit(15);
localMessagesQuery.findInBackground((FindCallback<ParseObject>) (msgsList, e) -> {
if (e == null) {
Log.d("msgs", "Retrieved " + msgsList.size() + " msg from cache");
for (ParseObject msg : msgsList
) {
Message message = new Message(msg.getString("owner"), msg.getString("content"), msg.getLong("timestamp"), msg.getString("state"));
message.toString();
messagesList.add(message);
messageAdapter.notifyDataSetChanged();
recyclerView.scrollToPosition(0);
}
updateCache(msgsList.get(0).getLong("timestamp"));
}else{
}
});
}
public void updateCache(Long timestamp){
ParseQuery NetworkMessagesQuery = ParseQuery.getQuery("Messages");
NetworkMessagesQuery.whereEqualTo("chatid", chatid);
NetworkMessagesQuery.whereGreaterThan("timestamp",timestamp);
NetworkMessagesQuery.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ONLY);
NetworkMessagesQuery.findInBackground((FindCallback<ParseObject>) (msgsList1, e1) -> {
if (e1 == null) {
for (ParseObject msg : msgsList1
) {
Message message = new Message(msg.getString("owner"), msg.getString("content"), msg.getLong("timestamp"), msg.getString("state"));
System.out.println(message.toString());
messagesList.add(0,message);
messageAdapter.notifyDataSetChanged();
recyclerView.scrollToPosition(0);
}
}else{
}
});
}
public void sendMsg(View v){
if (!messageboard.getText().toString().isEmpty()) {
final String msg = messageboard.getText().toString();
long timestamp = new Date().getTime();
ParseObject message = new ParseObject("Messages");
message.put("chatid",chatid);
message.put("owner",MainActivity.uid);
message.put("content",msg);
message.put("timestamp",timestamp);
message.put("state","sent");
message.saveInBackground();
@SuppressWarnings("rawtypes") ParseQuery query = ParseQuery.getQuery("Chats");
query.whereEqualTo("chatid",chatid);
query.getFirstInBackground((GetCallback<ParseObject>) (dataSnapshot, e) -> {
if(e==null) {
if(dataSnapshot!=null) {
dataSnapshot.put("lastmsg", msg);
dataSnapshot.put("timestamp", timestamp);
dataSnapshot.put("lastmsgowner", MainActivity.uid);
dataSnapshot.saveInBackground();
}else{
Log.i("chat is null", "sendMsg: datasnapshot is null");
}
}else{
Log.e("sendMsg", "chatid: "+chatid,e.fillInStackTrace() );
}
});
messageboard.getText().clear();
}
}
}