I am building a chat application and I have got a question about my fragment containing a listview with all the chats.
When a user receives a message the chats list is updated (showing the last message for every chat) (image 1).
When a chat is not visible and a message is received in that chat the user will receive a notification (image 2)
At this point the problem starts. When the user clicks on the notification the chats listview seems to be broken. When the user receives another message after clicking on the notification his/her phone will vibrate but the chats listview doesn't change/update.
The other views do work after clicking the notification.
Below is a piece of the code that handles the listview update.
protected PacketListener packetListener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
final Message message = (Message) packet;
if (message.getBody() != null) {
final String fromName = StringUtils.parseName(message.getFrom());
runOnUiThread(new Runnable(){
@Override
public void run() {
Boolean seen = false;
if(ChatFragment.currentChat != null && ChatFragment.currentChat.getContact().getUsername().equals(fromName) && VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
seen = true;
}
Long chat_id = chatsDataSource.getChatByContactId(contactsDataSource.getContactByUsername(fromName).getId()).getId();
ChatMessage newChatMessage = chatMessagesDataSource.insertChatMessage(chat_id, ConstantHelper.CHAT_MESSAGES_TYPE_RECEIVED, seen, DateHelper.getDatetime(), message.getBody());
Log.d("DEBUG", VisibilityHelper.sCurrentFragmentClassName);
if(VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatsFragment.fragmentClassName)) {
ChatsFragment chatsFragment = (ChatsFragment) getFragmentManager().findFragmentByTag(ChatsFragment.fragmentClassName);
Log.d("DEBUG", "REFRESHING");
chatsFragment.refreshChatsList();
}
if(!VisibilityHelper.appIsVisible()) {
notificationHelper.externalNotification(getBaseContext(), newChatMessage);
} else {
if(ChatFragment.currentChat != null && ChatFragment.currentChat.getContact().getUsername().equals(fromName) && VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
ChatFragment.chatsList.add(newChatMessage);
ChatFragment.chatsList.notifyDataSetChanged();
} else {
notificationHelper.internalNotification(getBaseContext(), newChatMessage);
}
}
}
});
}
}
};
Main Activity (how the fragments are created)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
Bundle extras = getIntent().getExtras();
initializeDataSources();
setLastContactUpdate();
if(usersDataSource.getCurrentUser() == null)
{
Intent LoginActivity = new Intent(getApplicationContext(), LoginActivity.class);
LoginActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(LoginActivity);
finish();
}
else
{
if(localServiceBinder == null)
localServiceBinder = new LocalServiceBinder();
bindLocalService();
runDispatchMethod(extras, savedInstanceState);
if (savedInstanceState == null) {
getAndSaveUserDetails();
GCMRegistrationID = registerGCM();
}
}
}
protected void runDispatchMethod(Bundle extras, Bundle savedInstanceState) {
if(savedInstanceState == null) {
startFragment(new ChatsFragment(), false);
}
if(extras != null && extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM) != null && !extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM).equals("")) {
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
startFragment(new ChatsFragment(), false);
ChatFragment chatFragment = new ChatFragment();
Bundle chatExtras = (Bundle) new Bundle();
chatExtras.putString(ConstantHelper.RECEIVED_MESSAGES_FROM, extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM));
chatFragment.setArguments(chatExtras);
startFragment(chatFragment);
return;
}
}
public void startFragment(Fragment newFragment) {
startFragment(newFragment, true);
}
public void startFragment(Fragment newFragment, Boolean addToBackstack) {
if(addToBackstack) {
getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).addToBackStack(newFragment.getClass().getName()).commit();
} else {
getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).commit();
}
getFragmentManager().executePendingTransactions();
}
Chats Adapter
public class ChatsAdapter extends BaseAdapter {
private List<Chat> chats;
private LayoutInflater inflater;
private String emptyLastMessageValue;
public ChatsAdapter(Context context, List<Chat> chats) {
this.chats = chats;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
emptyLastMessageValue = context.getText(R.string.fragment_chats_chat_created).toString();
}
@Override
public int getCount() {
return chats.size();
}
@Override
public Chat getItem(int position) {
return chats.get(position);
}
@Override
public long getItemId(int position) {
return chats.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View chatAdapterView = convertView;
if(convertView == null)
chatAdapterView = inflater.inflate(R.layout.adapter_chats, null);
TextView layout_fullname = (TextView) chatAdapterView.findViewById(R.id.fullname);
TextView layout_last_message = (TextView) chatAdapterView.findViewById(R.id.last_message);
TextView layout_unread_messages = (TextView) chatAdapterView.findViewById(R.id.unread_messages);
TextView layout_last_message_datetime = (TextView) chatAdapterView.findViewById(R.id.last_message_datetime);
Chat row = chats.get(position);
String firstname = row.getContact().getFirstname();
String fullname = row.getContact().getFullname();
if(firstname == null || firstname.equals(""))
fullname = StringHelper.ucfirst(row.getContact().getUsername());
layout_fullname.setText(fullname);
String last_message_value;
String last_message_datetime_value = "";
if(row.getLastMessage() == null) {
last_message_value = emptyLastMessageValue;
layout_last_message_datetime.setVisibility(TextView.GONE);
layout_unread_messages.setVisibility(TextView.GONE);
} else {
last_message_value = row.getLastMessage().getMessageBody();
last_message_datetime_value = DateHelper.toReadableDatetime(row.getLastMessage().getMessageDatetime());
layout_last_message_datetime.setText(last_message_datetime_value);
Integer unreadMessages = row.getUnreadMessages();
if(unreadMessages > 0) {
layout_unread_messages.setText(String.valueOf(unreadMessages));
layout_unread_messages.setVisibility(TextView.VISIBLE);
} else {
layout_unread_messages.setVisibility(TextView.GONE);
}
}
layout_last_message.setText(last_message_value);
return chatAdapterView;
}
}
Refresh Chats List function
public void refreshChatsList() {
Log.d("DEBUG", "It does come here!");
chats.clear();
chats.addAll(((MainActivity) getActivity()).chatsDataSource.getAllChats());
chats_adapter.notifyDataSetChanged();
}
Logcat output
07-06 20:12:43.892: D/SMACK(14948): 08:12:43 PM RCV (1106735848): <message id="3jRRg-24" to="[email protected]" type="chat" from="[email protected]/Smack"><body>Test</body></message>
07-06 20:12:43.962: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:43.962: D/DEBUG(14948): REFRESHING
07-06 20:12:43.962: D/DEBUG(14948): It does come here!
07-06 20:12:48.406: D/SMACK(14948): 08:12:48 PM RCV (1106735848): <message id="3jRRg-25" to="[email protected]" type="chat" from="[email protected]/Smack"><body>Test 2</body></message>
07-06 20:12:48.446: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:51.059: D/KUTZOOI(14948): HELEMAAL WÄCK
07-06 20:12:51.099: D/dalvikvm(14948): GC_FOR_ALLOC freed 161K, 3% free 9653K/9912K, paused 19ms, total 21ms
07-06 20:12:51.109: I/dalvikvm-heap(14948): Grow heap (frag case) to 13.272MB for 4000016-byte allocation
07-06 20:12:51.139: D/dalvikvm(14948): GC_FOR_ALLOC freed 1K, 2% free 13558K/13820K, paused 25ms, total 25ms
07-06 20:12:54.953: D/SMACK(14948): 08:12:54 PM RCV (1106735848): <message id="3jRRg-26" to="[email protected]" type="chat" from="[email protected]/Smack"><body>Test 3</body></message>
07-06 20:12:54.993: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:54.993: D/DEBUG(14948): REFRESHING
07-06 20:12:54.993: D/DEBUG(14948): It does come here!
Chats List
Notification
Make sure that you are working with the same fragment after returning to the activity through clicking a notification(judging by the way the problem appears). If you don't hold a reference to the same instance that the user sees, then any chat update will fail silently as you'll be updating only the background fragment(and not the visible one). The error seems to be in the runDispatchMethod()
where you do a transaction with a new fragment every time not checking if another instance of the ChatsFragment
is already available(in which case you would just call an update method on that instance).
(I would put a comment if I could)
I think the problem is the notifyingdatasetChanged();
Add this to your adapter
public void swapItems(List<Chat> chat) {
this.chats = chat;
notifyDataSetChanged();
}
Call this for new messages
chats_adapter.swapItems(((MainActivity) getActivity()).chatsDataSource.getAllChats());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With