I have Recycler view in Android and I need to implement load more at recycler view, I searched over internet but failed to solve my problem, this is my code please help
This is the adapter
public class NewsReycelerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
List<String> Dates , Titles , Details , Images;
public static String NewsDetail,NewsDate ,NewsTitle;
public final int TYPE_NEWS = 0;
public final int TYPE_LOAD = 1;
private int visibleThreshold = 2;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;
public NewsReycelerViewAdapter(RecyclerView recyclerView,Context context , List<String> stringsDate , List<String> stringTitles , List<String> stringDetails ,List<String> stringImage,final JPANewsFragment fragment) {
this.context = context;
this.Dates = stringsDate;
this.Titles = stringTitles;
this.Details = stringDetails;
this.Images = stringImage;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
fragment.getHtmlNewsData("1");
loading = true;
}
}
});
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType==TYPE_NEWS){
return new Item_Holder(inflater.inflate(R.layout.news_adapter_item,parent,false));
}else{
return new LoadHolder(inflater.inflate(R.layout.item_loading,parent,false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((Item_Holder)holder).Date.setText(Dates.get(position));
((Item_Holder)holder).Title.setText(Titles.get(position));
NewsDetail = Details.get(position);
NewsDate = Dates.get(position);
NewsTitle = Titles.get(position);
((Item_Holder)holder).itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)context).changeFragmentMethod(new NewsDetailsFragment(),context.getResources().getString(R.string.news_details));
}
});
}
#Override
public int getItemCount() {
return Dates == null ? 0 : Dates.size();
}
//////////////////////////////////////////////////////////////////////////////////
public class Item_Holder extends RecyclerView.ViewHolder {
TextView Title , Date ;
ImageView jpaThumbnail;
public Item_Holder(View itemView) {
super(itemView);
Title = (TextView) itemView.findViewById(R.id.textView_title);
Date = (TextView) itemView.findViewById(R.id.textView_date);
jpaThumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
}
}
static class LoadHolder extends RecyclerView.ViewHolder{
public LoadHolder(View itemView) {
super(itemView);
}
}
#Override
public int getItemViewType(int position) {
return Dates.get(position) != null ? TYPE_NEWS : TYPE_LOAD;
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.onLoadMoreListener = mOnLoadMoreListener;
}
public void setLoaded() {
loading = false;
}
}
First api have 10 item and when user swipes, I need to load more from another page,
and this is the code written in my main activity
newsReycelerViewAdapter = new NewsReycelerViewAdapter(recyclerViewNews,context, stringsDate, stringsTitle, stringsDetails,stringsImages,new JPANewsFragment());
recyclerViewNews.setLayoutManager(new LinearLayoutManager(context));
recyclerViewNews.setAdapter(newsReycelerViewAdapter);
loadingProgressBar.setVisibility(View.GONE);
newsReycelerViewAdapter.setLoaded();
newsReycelerViewAdapter.notifyDataSetChanged();
Please let me know how to solve this issue.
First add a addOnScrollListener() for your RecyclerView and detect scroll down
recyclerViewNews.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) {
Log.e("test","reached the last element of recyclerview");
visibleItemCount = mLinearLayoutManager.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
fetchData();
}
}
}
}
});
Second Create a function fetchData() to add more data to your adapter
then call on newsReycelerViewAdapter.notifyDataSetChanged(); to notify the dataset change and change loading=true
On your activity main create fields as
int pastVisiblesItems, visibleItemCount, totalItemCount;
boolean loading = true;
Here is example for Simple Implementation of LoadMore RecyclerView using a Simple Library compiled from the various sources.
Add this line in build.gradle
implementation 'com.hereshem.lib:awesomelib:2.0.1'
Create RecyclerView Layout in Activity with
<com.hereshem.lib.recycler.MyRecyclerView
android:id="#+id/recycler"
app:layoutManager="LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Create a ViewHolder by passing the class that supports
public static class EVHolder extends MyViewHolder<Events> {
TextView date, title, summary;
public EVHolder(View v) {
super(v);
date = v.findViewById(R.id.date);
title = v.findViewById(R.id.title);
summary = v.findViewById(R.id.summary);
}
#Override
public void bindView(Events c) {
date.setText(c.date);
title.setText(c.title);
summary.setText(c.summary);
}
}
Create Items List variable and adapters with very few lines by passing items, class and layout in the adapter
List<Events> items = new ArrayList<>();
MyRecyclerView recycler = findViewById(R.id.recycler);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
recycler.setAdapter(adapter);
ClickListener and LoadMore Listener can be added with following lines
recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
recycler.setOnLoadMoreListener(new MyRecyclerView.OnLoadMoreListener() {
#Override
public void onLoadMore() {
loadData();
}
});
loadData();
After the data is loaded this must be called
recycler.loadComplete();
When no LoadMore is required LoadMore layout can be hidden by calling
recycler.hideLoadMore();
Complete example can be found here
Hope this helps :)
My loadmore function looks like:
private void loadMoreMessages() {
DatabaseReference messageRef = mRootRef.child("messages").child(mThemaID);
Query messageQuery = messageRef.orderByKey().endAt(mLastKey).limitToLast(10);
messageQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Messages message = dataSnapshot.getValue(Messages.class);
String messageKey = dataSnapshot.getKey();
if(!mPrevKey.equals(messageKey)){
messagesList.add(itemPos++, message);
}else {
mPrevKey = mLastKey;
}
if(itemPos == 1){
mLastKey = messageKey;
}
mAdapter.notifyDataSetChanged();
mLinearLayout.scrollToPositionWithOffset(itemPos-1, 0);
mRefreshLayout.setRefreshing(false);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
and the listener:
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mCurrentPage++;
itemPos = 0;
loadMoreMessages();
}
});
maybe you can do something with this
Related
I'm trying to include pagination in my app what I want that for eg in my firebase I have 500 images that are to be shown in the recycler view what I want is first 10 or 15 images are loaded in the recycler view at the beginning and when the user reaches to the end of the last item(image) it loads next 10 images (just like Instagram or facebook )
Note:- if anyone wants more reference of my code please tell me I will
update my question
Here is my code
Home_Fragment.java
private boolean loading = true;
private int pastVisibleItems, visibleItemCount, totalItemCount;
#SuppressLint("SourceLockedOrientationActivity")
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
MaterialToolbar materialToolbar = view.findViewById(R.id.toolbar);
materialToolbar.setOnMenuItemClickListener(toolbarItemClickListener);
postRecyclerView = view.findViewById(R.id.recyclerViewHome);
shimmerFrameLayout = view.findViewById(R.id.shimmerEffect);
// this is for one item per scroll
// SnapHelper snapHelper = new PagerSnapHelper();
// snapHelper.attachToRecyclerView(verticalRecyclerView);
postRecyclerView.setAdapter(postsAdapter);
// listState = savedInstanceState.getParcelable("ListState");
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
postRecyclerView.setLayoutManager(
staggeredGridLayoutManager
);
getData();
postRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
visibleItemCount = staggeredGridLayoutManager.getChildCount();
totalItemCount = staggeredGridLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = staggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisibleItems = firstVisibleItems[0];
}
if (loading) {
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
loading = false;
getData();
Log.d("tag", "LOAD NEXT ITEM");
}
}
}
});
// setupFirebaseAuth();
shimmerFrameLayout.startShimmer();
mUploads = new ArrayList<>();
postsAdapter = new PostAdapter_Home(getContext(), mUploads);
postRecyclerView.setAdapter(postsAdapter);
postRecyclerView.scrollToPosition(Home_Fragment.saved_position);
return view;
}
private void getData() {
databaseReference.addValueEventListener(new ValueEventListener() {
#SuppressLint("NotifyDataSetChanged")
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
shimmerFrameLayout.stopShimmer();
shimmerFrameLayout.setVisibility(View.GONE);
postRecyclerView.setVisibility(View.VISIBLE);
mUploads.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
Upload upload = dataSnapshot.getValue(Upload.class);
assert upload != null;
upload.setmKey(dataSnapshot.getKey());
mUploads.add(upload);
}
}
postsAdapter.setUploads(mUploads);
//notify the adapter
postsAdapter.notifyDataSetChanged();
loading = true;
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
loading = true;
}
});
}
PostAdapter_Home.java // Adapter Class
public class PostAdapter_Home extends RecyclerView.Adapter<PostAdapter_Home.PostViewHolder> {
public static List<Upload> mUploads;
public Context mcontext;
public PostAdapter_Home(Context context, List<Upload> uploads) {
mUploads = uploads;
mcontext = context;
}
#NonNull
#Override
public PostViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
view = LayoutInflater.from(mcontext).inflate(R.layout.ex_home, parent, false);
return new PostViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PostViewHolder holder, int position) {
Shimmer shimmer = new Shimmer.ColorHighlightBuilder()
.setBaseColor(Color.parseColor("#F3F3F3"))
.setBaseAlpha(1)
.setHighlightColor(Color.parseColor("#E7E7E7"))
.setHighlightAlpha(1)
.setDropoff(50)
.build();
ShimmerDrawable shimmerDrawable = new ShimmerDrawable();
shimmerDrawable.setShimmer(shimmer);
Upload uploadCurrent = mUploads.get(position);
Glide.with(mcontext)
.load(uploadCurrent.getmImageUrl())
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.placeholder(shimmerDrawable)
.centerCrop()
.fitCenter()
.into(holder.imageView);
// holder.imageView.setOnClickListener(view -> changeScaleType(holder, position));
}
#Override
public int getItemCount() {
return mUploads.size();
}
public void setUploads(List<Upload> uploads){
mUploads=uploads;
}
public static class PostViewHolder extends RecyclerView.ViewHolder {
private final ShapeableImageView imageView;
public PostViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imagePostHome);
}
}
}
Update // Added Upload.java file code as requested in the comment section
Upload.java
package com.example.myappnotfinal.AdaptersAndMore;
import com.google.firebase.database.Exclude;
public class Upload {
private String mImageUrl;
private String mKey;
private String mUserName;
private String mComment;
public Upload() {
}
public Upload(String imageUrl) {
mImageUrl = imageUrl;
}
public String getmUserName() {
return mUserName;
}
public void setmUserName(String mUserName) {
this.mUserName = mUserName;
}
public String getmComment() {
return mComment;
}
public void setmComment(String mComment) {
this.mComment = mComment;
}
public String getmImageUrl() {
return mImageUrl;
}
public void setmImageUrl(String mImageUrl) {
this.mImageUrl = mImageUrl;
}
#Exclude
public String getmKey() {
return mKey;
}
#Exclude
public void setmKey(String Key) {
this.mKey = Key;
}
}
First you should separate fetching data logic from UI. Then your scroll controller (RecyclerView) should control which images should be called to download (so when it's loaded it should ask for first batch of images, when scroll happens - ask for another batch, etc.). And downloading and caching images is not a trivial task, that's why we have Glide and Coil in Android world.
As a side note please take a look at https://developer.android.com/topic/libraries/architecture/paging/v3-paged-data and https://developer.android.com/topic/libraries/architecture/paging.
Please check what you're adding to the list of mUploads because every time you add items, you clear the list upfront mUploads.clear(); which may be not what you wanted.
Some notes:
dont make it static public static List<Upload> mUploads;
don't need to store mcontext, Context is already there
strip the problem out of unncessary stuff (e.g. drop shimmer, fix the problem, add shimmer when fixed)
Here what you need to do is setLimit for pagination process.
Here is and example:
private void getUsers(String nodeId) {
Query query;
if (nodeId == null)
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.limitToFirst(mPostsPerPage);
else
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.startAt(nodeId)
.limitToFirst(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserModel user;
List<UserModel> userModels = new ArrayList<>();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
userModels.add(userSnapshot.getValue(UserModel.class));
}
mAdapter.addAll(userModels);
mIsLoading = false;
}
#Override
public void onCancelled(DatabaseError databaseError) {
mIsLoading = false;
}
});
}
So here you need to send last node id each time to get new list. After getting response just add your data to ArrayList or what ever logic you are using. Then just update RecyclerView like this:
blogRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true;
}
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
currentItems = manager.getChildCount();
totalItems = manager.getItemCount();
scrollOutItems = manager.findFirstVisibleItemPosition();
if (isScrolling && (currentItems + scrollOutItems == totalItems) && nextPage != null) {
isScrolling = false;
progressBar.setVisibility(View.VISIBLE);
getUsers(mlastNodeId);//here your last id will be
}
}
});
}
Hello there I have a recyclerview with images loaded from firebase I want to implement endless scroll but the issue I'm getting is with StaggeredGridLayoutManager and I have to use it I cant replace it with grid-layout
Note:- I have seen other answers on this topic but the majority of
answers are for LinearLayoutManager and some for GridLayout but there
is only one answer I found for StaggeredGridLayoutManager which I don't
know why it's not working for me
If you want more references of the code please tell me I will update
the question
Profile_Fragment.java
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile, container, false);
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
ImageView accountSettings = view.findViewById(R.id.account_Settings);
RelativeLayout relativeLayout = view.findViewById(R.id.snipet_profile);
profilePhoto = relativeLayout.findViewById(R.id.circleImageView);
editProfileButton = relativeLayout.findViewById(R.id.edit_profile_button);
uploadImageButton = view.findViewById(R.id.upload_image_profile);
progressBar = view.findViewById(R.id.progressBar_Profile);
editProfileButton.setOnClickListener(v -> {
Fragment edit_profile = new Edit_Profile();
assert getFragmentManager() != null;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, edit_profile);
transaction.addToBackStack(String.valueOf(edit_profile));
transaction.commit();
});
uploadImageButton.setOnClickListener(v -> {
BottomSheet_Upload bottomSheetSettings = new BottomSheet_Upload();
bottomSheetSettings.show(requireActivity().getSupportFragmentManager(), bottomSheetSettings.getTag());
});
accountSettings.setOnClickListener(
v -> {
BottomSheet_Settings bottomSheetSettings = new BottomSheet_Settings();
bottomSheetSettings.show(requireActivity().getSupportFragmentManager(), bottomSheetSettings.getTag());
}
);
postRecyclerView = view.findViewById(R.id.postRecyclerViewProfile);
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
postRecyclerView.setLayoutManager(
staggeredGridLayoutManager // I have 3 rows
);
postRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
visibleItemCount = staggeredGridLayoutManager.getChildCount();
totalItemCount = staggeredGridLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = staggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisibleItems = firstVisibleItems[0];
}
if (loading) {
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
loading = false;
getData();
Log.d("tag", "LOAD NEXT ITEM");
}
}
}
});
postRecyclerView.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.VISIBLE);
initImageLoader();
setProfileImage();
mUploads = new ArrayList<>();
postsAdapter = new PostAdapter(getContext(), mUploads);
postRecyclerView.setAdapter(postsAdapter);
postsAdapter.setOnItemClickListener(Profile_Fragment.this);
return view;
}
private void initImageLoader() {
UniversalImageLoader universalImageLoader = new UniversalImageLoader(getContext());
ImageLoader.getInstance().init(universalImageLoader.getConfig());
}
private void setProfileImage() {
String imgUrl = "www.64.media.tumblr.com/1276b4edef49034af70bda14325385e3/d8872c747cafa206-96/s500x750/aa915fc49a84b5295f0cd44145d655b66eb906a6.jpg";
UniversalImageLoader.setImage(imgUrl, profilePhoto, null, "https://");
}
private void getData() {
mStorage = FirebaseStorage.getInstance();
databaseEventListener = databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
progressBar.setVisibility(View.GONE);
postRecyclerView.setVisibility(View.VISIBLE);
mUploads.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
Upload upload = dataSnapshot.getValue(Upload.class);
Objects.requireNonNull(upload).setmKey(dataSnapshot.getKey());
mUploads.add(upload);
}
}
//notify the adapter
postsAdapter.notifyDataSetChanged();
loading = true;
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
loading = true;
}
});
}
Update 1
The main question code is changed with the current answer and Added the adapter class as requested
Problem
After implementing the answer there are no errors but the images are not loading in so I have updated the main code with the added answer
PostAdapter.java
public class PostAdapter extends RecyclerView.Adapter<PostAdapter.PostViewHolder> {
public static List<Upload> mUploads;
public Context mcontext;
private OnItemClickListener mListener;
/* ShimmerFrameLayout shimmerFrameLayout; */
public PostAdapter(Context context, List<Upload> uploads) {
mUploads = uploads;
mcontext = context;
}
#NonNull
#Override
public PostViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater.from(mcontext).inflate(R.layout.post_item_container_profile, parent, false);
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_item_container_profile, parent, false);
return new PostViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PostViewHolder holder, int position) {
Upload uploadCurrent = mUploads.get(position);
Shimmer shimmer = new Shimmer.ColorHighlightBuilder()
.setBaseColor(Color.parseColor("#F3F3F3"))
.setBaseAlpha(1)
.setHighlightColor(Color.parseColor("#E7E7E7"))
.setHighlightAlpha(1)
.setDropoff(50)
.build();
ShimmerDrawable shimmerDrawable = new ShimmerDrawable();
shimmerDrawable.setShimmer(shimmer);
Glide.with(mcontext)
.load(uploadCurrent.getmImageUrl())
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.placeholder(shimmerDrawable)
.centerCrop()
.fitCenter()
.into(holder.imageView);
}
#Override
public int getItemCount() {
return mUploads.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public interface OnItemClickListener {
void onClick(View view);
void onItemClick(int position);
void onDeleteClick(int position);
}
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener {
ShapeableImageView imageView;
PostViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imagePost);
itemView.setOnClickListener(this);
itemView.setOnCreateContextMenuListener(this);
}
#Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
MenuItem delete = menu.add(Menu.NONE, 2, 2, "Delete");
delete.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
if (item.getItemId() == 2) {
mListener.onDeleteClick(position);
return true;
}
}
}
return false;
}
}
}
For your first problem you already have a solution.
StaggeredGridLayoutManager staggeredGridLayoutManager = new
StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
postRecyclerView.setLayoutManager(
staggeredGridLayoutManager // I have 3 rows
);
For second problem:
postRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener({
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
visibleItemCount = staggeredGridLayoutManager .getChildCount();
totalItemCount = staggeredGridLayoutManager .getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if(firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisibleItems = firstVisibleItems[0];
}
if (loading) {
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
loading = false;
getData()
}
}
}
});
..........
..........
private void getData() {
mStorage = FirebaseStorage.getInstance();
databaseEventListener = databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
progressBar.setVisibility(View.GONE);
postRecyclerView.setVisibility(View.VISIBLE);
mUploads.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
Upload upload = dataSnapshot.getValue(Upload.class);
Objects.requireNonNull(upload).setmKey(dataSnapshot.getKey());
mUploads.add(upload);
}
}
//notify the adapter
postsAdapter.notifyDataSetChanged();
loading = true;
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
loading = true;
}
});
}
You might have to call the getData() initially in your onCreate() so that some data loads up on the screen and you have a scroll behavior.
Update:
The second parameter in a StaggeredGridLayoutManager is orientation so instead of context you have to pass orientation StaggeredGridLayoutManager.VERTICAL.
Needless to say, I came across a lot of proposed solutions for this particular problem. I removed scrollListener and implemented it inside my fragment, I used notifyItemRangeInserted instead of notifyDataSetChanged. The thing is, none of those solutions did work for me...I'm displaying a set of youtube videos in my app. My dataset is indeed updated; thing is when I scroll downwards, at some point the scroll position moves to the top i.e the very first item of my dataset Here's a snippet of my activity :
private void setUpRecyclerView()
{
mRecyclerView.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold))
{
loadMorePosts();
loading = true;
}
}
});
initAdapter();
}
private void initAdapter()
{
adapter = new MyAdapter(mDataSet, getActivity());
mRecyclerView.setAdapter(adapter);
skeletonScreen = Skeleton.bind(mRecyclerView)
.adapter(adapter)
.shimmer(true)
.angle(30)
.duration(1200)
.count(10)
.load(R.layout.youtube_item)
.show();
}
private void loadVideos(final OnLoadPlayListCallback videosCallback, String pageToken)
{
Call<FullChannelPlayListData> mcallPlayList = mYouTubeService.getPlayList(
Tags.VALUE_SNIPPET,
20,
mPlayListId,
getActivity().getResources().getString(R.string.youtube_data_api_key),
pageToken
);
mcallPlayList.enqueue(new Callback<FullChannelPlayListData>() {
#Override
public void onResponse(Call<FullChannelPlayListData> call, Response<FullChannelPlayListData> response) {
if (response.code() == 200)
{
Log.d("FullPlayListSuccessful", response.message());
videosCallback.onSuccessfulRequest(response.body());
}
else Log.d("FullPlayListUnsuccess", response.message());
}
#Override
public void onFailure(Call<FullChannelPlayListData> call, Throwable t) {
videosCallback.onFailureRequest(t);
}
});
}
#Override
public void onSuccessfulRequest(FullChannelPlayListData fullChannelPlayListData)
{
Log.d(TAG, "onSuccessfulRequest Item size = "+ fullChannelPlayListData.getItems().size());
if (StringUtils.isNotEmpty(mNextPageToken))
removeFooter();
for (FullPlayListItems mItem: fullChannelPlayListData.getItems())
{
FullPlayListItems randomItem = getVideoFromDataSet(mItem.getSnippet().getResourceId().getVideoId(), mDataSet);
if (randomItem == null) {
mDataSet.add(mItem);
}
}
adapter.notifyItemRangeInserted(adapter.getItemCount(), mDataSet.size());
mRecyclerView.postDelayed(new Runnable() {
#Override
public void run() {
skeletonScreen.hide();
}
}, 2000);
mNextPageToken = fullChannelPlayListData.getNextPageToken();
setLoaded();
}
public void setLoaded() {
loading = false;
}
I could use really use some help...
UPDATE MyAdapter class
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
private List<FullPlayListItems> mDataSet;
private Context mActivity;
private static final int YOUTUBE_ITEM_VIEW_TYPE = 0;
private static final int PROGRESS_BAR_ITEM_VIEW_TYPE = 1;
public MyAdapter(List<FullPlayListItems> mDataSet, Context mActivity) {
this.mDataSet = mDataSet;
this.mActivity = mActivity;
}
public class ProgressViewHolder extends RecyclerView.ViewHolder
{
#BindView(R.id.pBarLoadMorePosts)
ProgressBar pBarLoadMore;
public ProgressViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
#Override
public int getItemViewType(int position) {
return mDataSet.get(position) != null ? YOUTUBE_ITEM_VIEW_TYPE : PROGRESS_BAR_ITEM_VIEW_TYPE;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
RecyclerView.ViewHolder viewHolder;
if (viewType == PROGRESS_BAR_ITEM_VIEW_TYPE)
{
View pBarLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.footer_loader, parent, false);
viewHolder = new ProgressViewHolder(pBarLayoutView);
}
else
{
View postItemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.youtube_item, parent, false);
viewHolder = new YoutubeItemViewHolder(postItemLayoutView);
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
int viewType = getItemViewType(position);
FullPlayListItems mVideoItem = mDataSet.get(position);
switch (viewType)
{
case PROGRESS_BAR_ITEM_VIEW_TYPE:
ProgressViewHolder progressViewHolder = (ProgressViewHolder) holder;
progressViewHolder.pBarLoadMore.getIndeterminateDrawable().setColorFilter(CoreApplication.getRes().getColor(R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
break;
case YOUTUBE_ITEM_VIEW_TYPE:
default:
YoutubeItemViewHolder youtubeItemViewHolder = (YoutubeItemViewHolder) holder;
youtubeItemViewHolder.mVideoTitle.setText(mVideoItem.getSnippet().getTitle());
youtubeItemViewHolder.sdvYoutubeThumbnail.setImageURI(Uri.parse(mVideoItem.getSnippet().getThumbnails().getHigh().getUrl()));
}
}
#Override
public int getItemCount() {
return mDataSet != null ? mDataSet.size() : 0;
}
public class YoutubeItemViewHolder extends RecyclerView.ViewHolder
{
TextView mVideoTitle;
SimpleDraweeView sdvYoutubeThumbnail;
public YoutubeItemViewHolder(View itemView)
{
super(itemView);
mVideoTitle = (TextView)itemView.findViewById(R.id.tv_video_title);
sdvYoutubeThumbnail = (SimpleDraweeView)itemView.findViewById(R.id.sdv_thumbnail);
}
}
}
And here is my onViewCreated:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mPlayListId = getArguments().getString(Tags.YT_CHANNEL_PLAYLIST_ID);
setUpRecyclerView();
// Like I said initially mNextPageToken is empty
loadVideos(this, mNextPageToken);
}
Just notify the data change in the onSuccessfulRequest() method.
adapter.notifyDataSetChanged();
I don't know this answer is helpful to you. anyway please try,
Add this method to your MyAdapter
public void addItem(VideoSectionsActivity item){
mDataSet.add(item);
notifyItemInserted(mDataSet.size() - 1);
}
And change your onSuccessfulRequest()
#Override
public void onSuccessfulRequest(FullChannelPlayListData fullChannelPlayListData)
{
Log.d(TAG, "onSuccessfulRequest Item size = "+ fullChannelPlayListData.getItems().size());
if (StringUtils.isNotEmpty(mNextPageToken))
removeFooter();
for (FullPlayListItems mItem: fullChannelPlayListData.getItems())
{
FullPlayListItems randomItem = getVideoFromDataSet(mItem.getSnippet().getResourceId().getVideoId(), mDataSet);
if (randomItem == null) {
adapter.addItem(mItem);
}
}
mRecyclerView.postDelayed(new Runnable() {
#Override
public void run() {
skeletonScreen.hide();
}
}, 2000);
mNextPageToken = fullChannelPlayListData.getNextPageToken();
setLoaded();
}
Updated
And also rearrange your code in activity
private void setUpRecyclerView()
{
mRecyclerView.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
initAdapter();
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold))
{
loadMorePosts();
loading = true;
}
}
});
}
I have a problem with RecyclerView. I implemented OnScrollListener to it and when user reach end of list it should load a new data depending on index (index 1 loading first 8 index 2 loading second 8 etc) But problem is as soon as adapter start loading new data it scroll me to top :(
This is my code from function where I'm calling server:
public void showlist() {
progressBar = new ProgressDialog(getActivity());
progressBar.setMessage("Please wait ...");
progressBar.show();
NetworkSDK.getInstance().getNews(size, offset, new Callback<List<News>>() {
#Override
public void onResponse(Call<List<News>> call, Response<List<News>> response) {
if (response.code() == 401) {
Intent intent = new Intent(getContext(), MainPreLogin.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
progressBar.dismiss();
startActivity(intent);
SharedData.getInstance().removeString("token");
}
if (response.isSuccess()) {
newsAdapter = new NewsAdapterRecycler(listNews);
if (response.body().size() == 0) {
progressBar.dismiss();
Toast.makeText(getActivity(), R.string.noMorenews, Toast.LENGTH_SHORT).show();
} else {
for (int i = 0; i < response.body().size(); i++) {
newsAdapter.insert(newsAdapter.getItemCount() + 1, response.body().get(i));
}
newsList.setAdapter(newsAdapter);
newsAdapter.notifyDataSetChanged();
progressBar.dismiss();
}
}
}
#Override
public void onFailure(Call<List<ba.project.models.News>> call, Throwable t) {
Toast.makeText(getContext(), R.string.errorNoconnection, Toast.LENGTH_LONG).show();
progressBar.dismiss();
}
});
}
This is my adapter:
public class NewsAdapterRecycler extends RecyclerView.Adapter<NewsAdapterRecycler.MyViewHolder> {
private static int selectedItem = -1;
ArrayList<News> newslist;
Context context;
public NewsAdapterRecycler(ArrayList<News> newslist) {
this.newslist = newslist;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_news_layout, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
View view = null;
Log.d("Pozicija News",String.valueOf(position));
News news = newslist.get(position);
holder.shortText.setText(news.getIntro());
holder.name.setText(news.getSubject());
if (news.getImagePath().equals(""))
Picasso.with(context).load(R.drawable.logo_Def).fit().centerCrop().into(holder.picture);
else
Picasso.with(context).load(news.getImagePath()).fit().centerCrop().into(holder.picture);
holder.date.setText(news.getShortDate());
if (selectedItem == position)
holder.itemView.setSelected(true);
}
#Override
public int getItemCount() {
return newslist.size();
}
public void insert(int position, News data) {
newslist.add(position - 1, data);
notifyItemInserted(position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView shortText;
TextView date;
ImageView picture;
public MyViewHolder(View view) {
super(view);
this.name=(TextView)view.findViewById(R.id.news_title);
this.shortText=(TextView)view.findViewById(R.id.news_desc);
this.picture=(ImageView)view.findViewById(R.id.news_image);
this.date=(TextView)view.findViewById(R.id.news_date);
}
}
}
This is my scrolllsitener
newsList.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = newsList.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
Log.d("Visibleitem", String.valueOf(visibleItemCount));
Log.d("totalItem", String.valueOf(totalItemCount));
Log.d("firstvisibleitem", String.valueOf(firstVisibleItem));
if (restarting) {
previousTotal = 0;
visibleThreshold = 5;
}
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
offset++;
showlist();
// Do something
loading = true;
restarting = false;
}
}
});
Also if it's meter this funciton is called every time when user scroll to this fragment via this:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && !areNewsLoaded) {
listNews = new ArrayList<>();
offset=0;
showlist();
restarting = true;
}
}
I tried solutions posted above but none worked. Helpfully I manage to find some fix. Solution is in 3 magic lines :
private Parcelable recyclerViewState;
recyclerViewState = newsList.getLayoutManager().onSaveInstanceState();
newsList.getLayoutManager().onRestoreInstanceState(recyclerViewState);
So basically I added 2. line before adding new content to my list and I guess it remember current position and I added 3. line after adding content so I assume this piece of code remember position
Try using notifyDataSetChanged() instead of notifyItemInserted().
A new insert method:
public void insert(News data) {
newslist.add(data);
notifyDataSetChanged();
}
Also i suggest create method to append all news at one time and use addAll method of ArrayList
try something like this ,
first you have to create interface
public interface Update{
public void OnDBUpdate();
}
then in Main Activity or somewhere add this
public class MainActivity extends AppCompatActivity implements DialogFragUpdateListener
and create method where you call the Recycler adapter
public void OnDBUpdate() {
dbList =helpher.getDataFromDB();
mAdapter = new RecyclerAdapter(this,dbList);
mRecyclerView.setAdapter(mAdapter);
}
and the last step ,, call the method where you need to update recycler
((Update) getActivity()).OnDBUpdate();
hope this help :)
I'm fairly new to Android and I'm building and app with a group of friends from college . The problem that we have run into is that when filling the list of elements to display by getting data from a server the data loads and gets added to a list but the recyclerView never displays it (even after calling NotifyDataSetChanged from my custom Adapter) . Back when we used hardcoded data to test the app , this never happened.
The strange part is that the list of elements get displayed on the recyclerView after I turn off the display and then turn it back on (onBindViewHolder of my custom Adapter gets called when I turn the screen back on).Moreover , if I replace the fragment that contains the recyclerView with another and then return to it the data gets loaded to the list but not shown.
What I want to know is why is this happening and what can I do to solve it (and by solve it I mean showing the recyclerView populated with the correct items right as I launch the fragment and updating the recyclerView when I add more elements to the list)
We are using a custom adpater and Retrofit to get data from the server.
Here is the code
Fragment that contains the recyclerView
public class EventViewListFragment extends Fragment implements EventListAdapter.ClickListener{
private RestClient restClient;
private Builder builder;
private String token ;
private boolean userScrolled = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
private LinearLayoutManager mLayoutManager;
private RecyclerView recyclerView;
private EventListAdapter eventListAdapter;
private Button btnNewEvent;
FloatingActionButton suggestFAB;
private int currentPage=1;
public EventViewListFragment(){
restClient = new RestClient();
}
#Override
public void onCreate(Bundle savedInstanceState) {
System.out.println("Se llamo al onCreate de EventViewListFragment");
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
System.out.println("se llamo al onCreateView de EvENT List Fragment");
// Inflate the layout for this fragment
View layout =inflater.inflate(R.layout.fragment_events_list, container, false);
setUpElements(layout);
addListeners();
return layout;
}
private void setUpElements(View layout)
{
recyclerView = (RecyclerView) layout.findViewById(R.id.eventList);
eventListAdapter = new EventListAdapter(getActivity());
eventListAdapter.setClickListener(this);
eventListAdapter.setData(getInitialData());
recyclerView.setAdapter(eventListAdapter);
mLayoutManager=new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
suggestFAB = (FloatingActionButton) layout.findViewById(R.id.suggestFAB);
builder = new Builder();
}
private void addListeners()
{
addNewEventListener();
addScrollBottomListener();
}
private void addNewEventListener()
{
/*btnNewEvent.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view)
{
EventsActivity.getInstance().toNewEventForm();
}
});*/
suggestFAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EventsActivity.getInstance().toNewEventForm();
currentPage=1;
}
});
}
public List<Event> getInitialData()
{
List<Event> data=new ArrayList<>();
data = getEvents(data);
return data;
}
#Override
public void itemClicked(View view, int position) {
EventsActivity.getInstance().toEventPage(eventListAdapter.getItemAtPos(position));
currentPage=1;
}
private void addScrollBottomListener() {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
userScrolled = true;
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx,
int dy) {
super.onScrolled(recyclerView, dx, dy);
// Here get the child count, item count and visibleitems
// from layout manager
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if (userScrolled && (visibleItemCount + pastVisiblesItems) == totalItemCount) {
userScrolled = false;
addNewElementsToList();
}
}
});
}
private void addNewElementsToList()
{
Toast.makeText(getActivity(), "Cargando Mas Elementos", Toast.LENGTH_SHORT).show();
eventListAdapter.setData(getEvents(eventListAdapter.getData()));
}
private List<Event> getEvents(final List<Event> eventsList)
{
System.out.println("Asignando CALL");
Call<JsonElement> eventPage = restClient.getConsumerService().getEvents(token, "", currentPage, 10);
System.out.println("Enquequeing");
eventPage.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Response<JsonElement> response) {
JsonObject responseBody = response.body().getAsJsonObject();
if (responseBody.has("events")) {
JsonArray jsonArray = responseBody.getAsJsonArray("events");
System.out.println(jsonArray.size());
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject storedObject = jsonArray.get(i).getAsJsonObject();
Event current = new Event();
current.setEventId(storedObject.get("id").getAsInt());
current.setName(storedObject.get("title").getAsString());
Calendar startCal = new GregorianCalendar();
startCal.setTimeInMillis((storedObject.get("starts_at").getAsLong()) * 1000);
current.setStartDateTime(startCal);
Calendar endCal = new GregorianCalendar();
endCal.setTimeInMillis((storedObject.get("ends_at").getAsLong()) * 1000);
current.setFinishDateTime(endCal);
current.setImgUrl(storedObject.get("image").getAsString());
eventsList.add(current);
}
} else {
if (responseBody.has("error")) {
System.out.println("ERROR");
wan.wanmarcos.models.Error error = builder.buildError(responseBody.get("error").getAsJsonObject());
Toast.makeText(getActivity(), "Error : " + error.toString(), Toast.LENGTH_SHORT).show();
} else {
}
}
}
#Override
public void onFailure(Throwable t) {
}
});
eventListAdapter.notifyDataSetChanged();
currentPage++;
return eventsList;
}
}
Custom Adapter for RecyclerView
public class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.EventListViewHolder>{
private LayoutInflater inflater;
private List<Event> data = Collections.emptyList();
private Context context;
private ClickListener clickListener;
public EventListAdapter(Context context){
inflater = LayoutInflater.from(context);
this.context=context;
}
#Override
public EventListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.event_list_item, parent, false);
EventListViewHolder holder = new EventListViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(EventListViewHolder holder, int position) {
System.out.println("se llamo al onBindViewHolder de ELA");
Event current = getData().get(position);
holder.title.setText(current.getName());
Picasso.with(context)
.load(current.getImgUrl())
.into(holder.img);
String startDateAndTime = current.CalendarToString(current.getStartDateTime())+" - "+current.CalendarToString(current.getFinishDateTime());
holder.dateAndTime.setText(startDateAndTime);
}
public void setClickListener(ClickListener clickListener){
this.clickListener=clickListener;
}
#Override
public int getItemCount() {
return getData().size();
}
public List<Event> getData() {
return data;
}
public void setData(List<Event> data) {
this.data = data;
}
class EventListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title;
TextView dateAndTime;
ImageView img;
public EventListViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
title = (TextView) itemView.findViewById(R.id.eventListTitle);
img = (ImageView) itemView.findViewById(R.id.eventListImage);
dateAndTime =(TextView) itemView.findViewById(R.id.eventListDateAndTime);
}
#Override
public void onClick(View v) {
if(clickListener!=null)
{
clickListener.itemClicked(v,getPosition());
}
}
}
public Event getItemAtPos(int pos)
{
return getData().get(pos);
}
public interface ClickListener{
public void itemClicked(View view,int position);
}
}
Fragment XML File
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="wan.wanmarcos.fragments.EventViewListFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/eventList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
>
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/suggestFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
app:layout_anchorGravity="bottom|right|end"
android:layout_margin="16dp"
android:clickable="true"
android:src="#mipmap/ic_add_white_48dp" />
</android.support.design.widget.CoordinatorLayout>
eventsList in your Activity and data in your Adapter are two different collections. You are filling up the former but not the latter.
Intialize data with new ArrayList<> instead of Collections.emptyList(); and then add a method in your Adapter, call addAll, like that:
public void addAll(final List<Event> new events) {
final int currentCount = data.size();
synchronized(data) {
data.addAll(events);
}
if (Looper.getMainLooper() == Looper.myLooper()) {
notifyItemRangeInserted(currentCount, events.size());
} else {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
notifyItemRangeInserted(currentCount, events.size());
}
});
}
}
the if else checks if you are calling addAll from the ui thread or from a different thread and call notifyItemRangeInserted in a safe way. In the Activity when onResponse is invoked, after you filled up completely eventsList, just call eventListAdapter.addAll(eventsList)