Added pager for chat messages to prevent long loading time
This commit is contained in:
parent
8822e63c0e
commit
41ed28e7f6
3 changed files with 155 additions and 8 deletions
|
@ -69,6 +69,7 @@ import java.io.IOException;
|
|||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||
|
@ -93,6 +94,7 @@ public class ChatEventsAdapter extends SelectableAdapter<ChatBubbleViewHolder> {
|
|||
mContext = mFragment.getActivity();
|
||||
mItemResource = itemResource;
|
||||
mHistory = new ArrayList<>(Arrays.asList(history));
|
||||
Collections.reverse(mHistory);
|
||||
mParticipants = participants;
|
||||
mClickListener = clickListener;
|
||||
mListener = new ChatMessageListenerStub() {
|
||||
|
@ -414,9 +416,16 @@ public class ChatEventsAdapter extends SelectableAdapter<ChatBubbleViewHolder> {
|
|||
}
|
||||
|
||||
public void addToHistory(EventLog log) {
|
||||
mHistory.add(log);
|
||||
notifyDataSetChanged();
|
||||
notifyItemChanged(0);
|
||||
mHistory.add(0, log);
|
||||
notifyItemInserted(0);
|
||||
}
|
||||
|
||||
public void addAllToHistory(ArrayList<EventLog> logs) {
|
||||
int currentSize = mHistory.size() - 1;
|
||||
Collections.reverse(logs);
|
||||
mHistory.addAll(logs);
|
||||
notifyItemRangeInserted(currentSize + 1, logs.size());
|
||||
}
|
||||
|
||||
public void setContacts(ArrayList<LinphoneContact> participants) {
|
||||
|
@ -425,6 +434,7 @@ public class ChatEventsAdapter extends SelectableAdapter<ChatBubbleViewHolder> {
|
|||
|
||||
public void refresh(EventLog[] history) {
|
||||
mHistory = new ArrayList<>(Arrays.asList(history));
|
||||
Collections.reverse(mHistory);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
|
104
src/android/org/linphone/chat/ChatScrollListener.java
Normal file
104
src/android/org/linphone/chat/ChatScrollListener.java
Normal file
|
@ -0,0 +1,104 @@
|
|||
package org.linphone.chat;
|
||||
|
||||
/*
|
||||
ChatScrollListener.java
|
||||
Copyright (C) 2010-2018 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
public abstract class ChatScrollListener extends RecyclerView.OnScrollListener {
|
||||
// The minimum amount of items to have below your current scroll position
|
||||
// before loading more.
|
||||
private int visibleThreshold = 5;
|
||||
// The current offset index of data you have loaded
|
||||
private int currentPage = 0;
|
||||
// The total number of items in the dataset after the last load
|
||||
private int previousTotalItemCount = 0;
|
||||
// True if we are still waiting for the last set of data to load.
|
||||
private boolean loading = true;
|
||||
// Sets the starting page index
|
||||
private int startingPageIndex = 0;
|
||||
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
|
||||
public ChatScrollListener(LinearLayoutManager layoutManager) {
|
||||
mLayoutManager = layoutManager;
|
||||
}
|
||||
|
||||
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
|
||||
int maxSize = 0;
|
||||
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
|
||||
if (i == 0) {
|
||||
maxSize = lastVisibleItemPositions[i];
|
||||
}
|
||||
else if (lastVisibleItemPositions[i] > maxSize) {
|
||||
maxSize = lastVisibleItemPositions[i];
|
||||
}
|
||||
}
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
// This happens many times a second during a scroll, so be wary of the code you place here.
|
||||
// We are given a few useful parameters to help us work out if we need to load some more data,
|
||||
// but first we check if we are waiting for the previous load to finish.
|
||||
@Override
|
||||
public void onScrolled(RecyclerView view, int dx, int dy) {
|
||||
int lastVisibleItemPosition = 0;
|
||||
int totalItemCount = mLayoutManager.getItemCount();
|
||||
|
||||
lastVisibleItemPosition = mLayoutManager.findLastVisibleItemPosition();
|
||||
|
||||
// If the total item count is zero and the previous isn't, assume the
|
||||
// list is invalidated and should be reset back to initial state
|
||||
if (totalItemCount < previousTotalItemCount) {
|
||||
this.currentPage = this.startingPageIndex;
|
||||
this.previousTotalItemCount = totalItemCount;
|
||||
if (totalItemCount == 0) {
|
||||
this.loading = true;
|
||||
}
|
||||
}
|
||||
// If it’s still loading, we check to see if the dataset count has
|
||||
// changed, if so we conclude it has finished loading and update the current page
|
||||
// number and total item count.
|
||||
if (loading && (totalItemCount > previousTotalItemCount)) {
|
||||
loading = false;
|
||||
previousTotalItemCount = totalItemCount;
|
||||
}
|
||||
|
||||
// If it isn’t currently loading, we check to see if we have breached
|
||||
// the visibleThreshold and need to reload more data.
|
||||
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
|
||||
// threshold should reflect how many total columns there are too
|
||||
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
|
||||
currentPage++;
|
||||
onLoadMore(currentPage, totalItemCount, view);
|
||||
loading = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Call this method whenever performing new searches
|
||||
public void resetState() {
|
||||
this.currentPage = this.startingPageIndex;
|
||||
this.previousTotalItemCount = 0;
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
// Defines the process for actually loading more data based on page
|
||||
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
|
||||
}
|
|
@ -32,6 +32,8 @@ import android.graphics.Rect;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
|
@ -80,6 +82,8 @@ import org.linphone.ui.SelectableHelper;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
|
@ -87,7 +91,9 @@ import static org.linphone.fragments.FragmentsAvailable.CHAT;
|
|||
|
||||
public class GroupChatFragment extends Fragment implements ChatRoomListener, ContactsUpdatedListener, ChatBubbleViewHolder.ClickListener, SelectableHelper.DeleteListener {
|
||||
private static final int ADD_PHOTO = 1337;
|
||||
private static final int MESSAGES_PER_PAGE = 20;
|
||||
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private ImageView mBackButton, mCallButton, mBackToCallButton, mGroupInfosButton;
|
||||
private ImageView mAttachImageButton, mSendMessageButton;
|
||||
private TextView mRoomLabel, mParticipantsLabel, mRemoteComposing;
|
||||
|
@ -106,6 +112,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
private ArrayList<LinphoneContact> mParticipants;
|
||||
private LinearLayoutManager layoutManager;
|
||||
private int mContextMenuMessagePosition;
|
||||
private ChatScrollListener mChatScrollListener;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
@ -218,9 +225,17 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
|
||||
mChatEventsList = view.findViewById(R.id.chat_message_list);
|
||||
mSelectionHelper = new SelectableHelper(view, this);
|
||||
layoutManager = new LinearLayoutManager(mContext);
|
||||
layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, true);
|
||||
mChatEventsList.setLayoutManager(layoutManager);
|
||||
|
||||
mChatScrollListener = new ChatScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
loadMoreData(totalItemsCount);
|
||||
}
|
||||
};
|
||||
mChatEventsList.addOnScrollListener(mChatScrollListener);
|
||||
|
||||
if (getArguments() != null) {
|
||||
String fileSharedUri = getArguments().getString("fileSharedUri");
|
||||
if (fileSharedUri != null) {
|
||||
|
@ -350,9 +365,9 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
eventLog.deleteFromDatabase();
|
||||
}
|
||||
if (mChatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) {
|
||||
mEventsAdapter.refresh(mChatRoom.getHistoryMessageEvents(0));
|
||||
mEventsAdapter.refresh(mChatRoom.getHistoryMessageEvents(MESSAGES_PER_PAGE));
|
||||
} else {
|
||||
mEventsAdapter.refresh(mChatRoom.getHistoryEvents(0));
|
||||
mEventsAdapter.refresh(mChatRoom.getHistoryEvents(MESSAGES_PER_PAGE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,6 +439,24 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private void loadMoreData(final int totalItemsCount) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int maxSize = mChatRoom.getHistoryEventsSize();
|
||||
if (totalItemsCount < maxSize) {
|
||||
int upperBound = totalItemsCount + MESSAGES_PER_PAGE;
|
||||
if (upperBound > maxSize) {
|
||||
upperBound = maxSize;
|
||||
}
|
||||
EventLog[] newLogs = mChatRoom.getHistoryRangeEvents(totalItemsCount, upperBound);
|
||||
ArrayList<EventLog> logsList = new ArrayList<>(Arrays.asList(newLogs));
|
||||
mEventsAdapter.addAllToHistory(logsList);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Keyboard management
|
||||
*/
|
||||
|
@ -563,9 +596,9 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
|
||||
if (mChatRoom == null) return;
|
||||
if (mChatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) {
|
||||
mEventsAdapter = new ChatEventsAdapter(this, mSelectionHelper, R.layout.chat_bubble, mChatRoom.getHistoryMessageEvents(0), mParticipants, this);
|
||||
mEventsAdapter = new ChatEventsAdapter(this, mSelectionHelper, R.layout.chat_bubble, mChatRoom.getHistoryMessageEvents(MESSAGES_PER_PAGE), mParticipants, this);
|
||||
} else {
|
||||
mEventsAdapter = new ChatEventsAdapter(this, mSelectionHelper, R.layout.chat_bubble, mChatRoom.getHistoryEvents(0), mParticipants, this);
|
||||
mEventsAdapter = new ChatEventsAdapter(this, mSelectionHelper, R.layout.chat_bubble, mChatRoom.getHistoryEvents(MESSAGES_PER_PAGE), mParticipants, this);
|
||||
}
|
||||
mSelectionHelper.setAdapter(mEventsAdapter);
|
||||
mChatEventsList.setAdapter(mEventsAdapter);
|
||||
|
@ -573,7 +606,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
}
|
||||
|
||||
public void scrollToBottom() {
|
||||
mChatEventsList.getLayoutManager().scrollToPosition(mEventsAdapter.getCount() - 1);
|
||||
mChatEventsList.getLayoutManager().scrollToPosition(0);
|
||||
}
|
||||
|
||||
public String getRemoteSipUri() {
|
||||
|
|
Loading…
Reference in a new issue