When the RecyclerView Reaches the end it will load another pair of data
but while loading RecyclerView, the empty view of RecyclerView is visible and if the empty view is clicked it gives me ArrayBoundaryExeption
so i need to stop scrolling when it isLoading
mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mUserAdapter = new UserAdapter();
mRecyclerView.setAdapter(mUserAdapter);
mUserAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
// if (Choose.equals("Local")) {
Log.e("haint", "Load More");
mUsers.add(null);
mUserAdapter.notifyItemInserted(mUsers.size() - 1);
dataLoadMore();
//mRecyclerView.setNestedScrollingEnabled(false);
// mRecyclerView.stopScroll();
//Load more data for reyclerview
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
Log.e("haint", "Load More 2");
// mRecyclerView.setNestedScrollingEnabled(false);
// mRecyclerView.stopScroll();
//Remove loading item
if (!mUsers.isEmpty()) {
mUsers.remove(mUsers.size() - 1);
mUserAdapter.notifyItemRemoved(mUsers.size());
}
for (int i = 0; i < lenMore; i++) {
LocalListView localListView = new LocalListView();
localListView.setJob_local_id(job_local_idM[i]);
localListView.setJob_typess(job_typessM[i]);
mUsers.add(localListView);
}
mUserAdapter.notifyDataSetChanged();
mUserAdapter.setLoaded();
}
}, 5000);
}
});
RecycleClick.addTo(mRecyclerView).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
#Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// YOUR CODE
if(mUserAdapter.isLoading){
//
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new
CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
Toast.makeText(getApplicationContext(),"Loading please
wait...",Toast.LENGTH_LONG).show();
}else if(position!=-1){
Intent is = new Intent(getApplicationContext(), WorkProfileLocal.class);
is.putExtra("job_local_idG", mUsers.get(position).getJob_local_id());
is.putExtra("user_idsG", mUsers.get(position).getUser_ids());
startActivity(is);
}
}
});
static class UserViewHolder extends RecyclerView.ViewHolder {
public TextView tvJobTitle;
public TextView tvJobWork;
public UserViewHolder(View itemView) {
super(itemView);
tvHirerName = (TextView) itemView.findViewById(R.id.tvWhatWork);
tvJobTitle = (TextView) itemView.findViewById(R.id.tvJobTitle);
}
}
static class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar1);
}
}
class UserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
private OnLoadMoreListener mOnLoadMoreListener;
private boolean isLoading;
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
public UserAdapter() {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
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 (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically();*/
}
isLoading = true;
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
}
}
});
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener;
}
#Override
public int getItemViewType(int position) {
return mUsers.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(WorkNow.this).inflate(R.layout.list_view_local_jobs, parent, false);
return new UserViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(WorkNow.this).inflate(R.layout.layout_loading_item, parent, false);
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
return new LoadingViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof UserViewHolder) {
LocalListView localListView = mUsers.get(position);
UserViewHolder userViewHolder = (UserViewHolder) holder;
userViewHolder.tvHirerName.setText(localListView.getUser_names());
userViewHolder.tvJobTitle.setText(localListView.getJob_titles().replaceAll("_", " "));
if (localListView.getImage().isEmpty()) {
userViewHolder.hirerPicLocal.setImageResource(R.drawable.blank_low);
} else{
Picasso.with(getApplicationContext())
.load(localListView.getImage())
.into(userViewHolder.hirerPicLocal);
}
} else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
/* mRecyclerView.stopNestedScroll();
mRecyclerView.stopScroll();
CustomGridLayoutManager ss= new CustomGridLayoutManager(WorkNow.this);
ss.setScrollEnabled(false);
mRecyclerView.setNestedScrollingEnabled(false);
linearLayoutManager.canScrollVertically(); */
}
}
#Override
public int getItemCount() {
return mUsers == null ? 0 : mUsers.size();
}
public void setLoaded() {
isLoading = false;
}
}
This Class i got from StackOverFlow to StopScroll But it is not working.
public class CustomGridLayoutManager extends LinearLayoutManager {
private boolean isScrollEnabled = true;
public CustomGridLayoutManager(Context context) {
super(context);
}
public void setScrollEnabled(boolean flag) {
this.isScrollEnabled = flag;
}
#Override
public boolean canScrollVertically() {
//Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
return isScrollEnabled && super.canScrollVertically();
}
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(WorkNow.this) {
#Override
public boolean canScrollVertically() {
return false;
}
};
Related
I was following this tutorial to implement pagination, and I was following it keenly, but I am uncertain how I should modify my current activity to implement OnLoadMoreListener. I am using an ApiService from retrofit to load data, unlike the tutorial that generates random strings.
This is how my current RecyclerView adapter looks like:
public class CuratedSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static int VIEW_TYPE_HEADER = 0;
private static int VIEW_TYPE_ITEM = 1;
private static int VIEW_TYPE_LOADING = 2;
private int lastVisibleItem, totalItemCount;
private int visibleThreshold = 2;
private boolean isLoading;
private List<Object> itemList;
private OnLoadMoreListener onLoadMoreListener;
public CuratedSectionAdapter(RecyclerView recyclerView, List<Object> itemList) {
this.itemList = itemList;
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 (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
}
private class ItemViewHolder extends RecyclerView.ViewHolder {
RecyclerView itemRecyclerView;
CuratedSectionNestedAdapter nestedAdapter;
LinearLayoutManager layoutManager;
ItemViewHolder(View view) {
super(view);
itemRecyclerView = view.findViewById(R.id.recyclerView_nested);
layoutManager = new LinearLayoutManager(view.getContext(), LinearLayoutManager.HORIZONTAL, false);
}
}
private class HeaderViewHolder extends RecyclerView.ViewHolder {
TextView textViewHeader;
Typeface montserratMedium = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/Montserrat-Medium.ttf");
HeaderViewHolder(View view) {
super(view);
textViewHeader = view.findViewById(R.id.textView_header);
textViewHeader.setTypeface(montserratMedium);
}
}
private class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View view) {
super(view);
progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == VIEW_TYPE_HEADER) {
HeaderViewHolder viewHolder = (HeaderViewHolder) holder;
CuratedSectionHeader header = (CuratedSectionHeader) itemList.get(position);
viewHolder.textViewHeader.setText(header.getHeaderName());
} else if (holder.getItemViewType() == VIEW_TYPE_ITEM) {
ItemViewHolder viewHolder = (ItemViewHolder) holder;
List<CuratedSectionItem> items = (List<CuratedSectionItem>) itemList.get(position);
if (viewHolder.nestedAdapter != null) {
viewHolder.nestedAdapter.setItems(items);
} else {
viewHolder.nestedAdapter = new CuratedSectionNestedAdapter(items);
viewHolder.itemRecyclerView.setLayoutManager(viewHolder.layoutManager);
viewHolder.itemRecyclerView.setAdapter(viewHolder.nestedAdapter);
}
} else if (holder.getItemViewType() == VIEW_TYPE_LOADING) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_HEADER) {
return new HeaderViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.main_explore_header_row, parent, false));
} else if (viewType == VIEW_TYPE_ITEM) {
return new ItemViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.main_explore_row, parent, false));
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
return new LoadingViewHolder(view);
}
throw new RuntimeException("Adapter " + viewType + "not found");
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public int getItemViewType(int position) {
if (itemList.get(position) instanceof CuratedSectionHeader) {
return VIEW_TYPE_HEADER;
} else {
return itemList.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.onLoadMoreListener = mOnLoadMoreListener;
}
public void setLoaded() {
isLoading = false;
}
}
The current architecture of my activity uses private classes to make API calls and load the data. At the moment, all items are loaded at once, but ideally there should be only 2 items loaded at a time. I am uncertain how I should load additional items by calling the API service again when I scroll to the bottom. At the very least, I am certain that I will have to use curatedSectionAdapter.setOnLoadMoreListener somehow.
This is how I load all of the items at the moment:
private class Sections {
List<CuratedSection> sections = new ArrayList<>();
public Thread[] thread;
private Sections() {}
public void setSections(ArrayList<CuratedSection> sections) {
this.sections = sections;
}
public void setSectionStories(String sectionId, List<CuratedSectionItem> stories) {
for(CuratedSection s : sections){
if(s.id != null && s.id.equals(sectionId)) {
s.stories = stories;
}
}
}
public void loadStories(String sessionKey) {
thread = new Thread[sections.size()];
for( int s = 0; s < sections.size(); s++) {
thread[s] = new Thread(new LoadStories(sessionKey, sections.get(s)));
thread[s].start();
}
for( int f = 0; f < sections.size(); f++) {
try {
thread[f].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
recyclerView.setLayoutManager(layoutManager);
curatedSectionAdapter = new CuratedSectionAdapter(recyclerView, this.getAdapterInfo());
recyclerView.setAdapter(curatedSectionAdapter);
}
public void loadSections(int numSections) {
swipeRefreshLayout.setRefreshing(false);
LoadSections load = new LoadSections(numSections);
load.run();
}
public List<Object> getAdapterInfo() {
List<Object> list = new ArrayList<>();
for (int i = 0; i < sections.size(); i++) {
CuratedSection section = sections.get(i);
CuratedSectionHeader header = new CuratedSectionHeader();
header.setHeaderName(section.header);
list.add(header);
list.add(section.stories);
}
return list;
}
}
private class LoadSections implements Runnable {
int numSections;
LoadSections(int numSections) {
this.numSections = numSections;
}
#Override
public void run() {
SharedPreferences prefs = getSharedPreferences("user_session", MODE_PRIVATE);
final String sessionKey = prefs.getString("session_key", null);
Call<JsonArray> call;
call = TravelersApi.endpoint().getCuratedSections(sessionKey);
call.enqueue(new Callback<JsonArray>() {
#Override
public void onResponse(Call<JsonArray> call, Response<JsonArray> response) {
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawSections = response.body();
if(rawSections.size() == 0) {
//TODO: show placeholder
return;
}
ArrayList<CuratedSection> sections = new ArrayList<>();
for(int i = 0; i < numSections; i++) {
JsonObject jSection = rawSections.get(i).getAsJsonObject();
final CuratedSection section = new CuratedSection();
section.id = jSection.get("id").getAsString();
section.header = jSection.get("section_header").getAsString();
section.topicCount = jSection.get("topic_count").getAsInt();
section.isShown = jSection.get("is_shown").getAsBoolean();
section.stories = new ArrayList<>();
sections.add(section);
}
curated.setSections(sections);
curated.loadStories(sessionKey);
spinner.clearAnimation();
spinner.setVisibility(View.GONE);
header.setVisibility(View.VISIBLE);
swipeRefreshLayout.setVisibility(View.VISIBLE);
}
#Override
public void onFailure(Call<JsonArray> call, Throwable t) {
Log.d("ERROR!", t.toString());
t.printStackTrace();
}
});
}
}
You can achieve this by directly setting scroll listener to your recycler view.
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 (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// Call Load more method here to load next page data
// Prevent multiple calls by using a boolean
isLoading=true; // boolean to Prevent multiple calls
}
}
});
OnLoadMoreListener is a interface you need to register it first.
For pagination your server should process the pagination count. So you also need the api to perform on page limit .
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 try to downloading image from server with volley and show them in recyclerview.
it is work correctly but the downloading image is very low.
(the size of each image approximately 50 kb).
what can i do?
is there better and optimize code than it?
this is my helper class:
public class StartActivity {
// for recyclerView - downLoad Data
private static final int LIMIT = 6;
OnLoadMoreListener onLoadMoreListener;
int idImage = 1;
private List<StructUser> structList = new ArrayList<>();
private AdapterUser adapter;
private int CURRENT_ITEM = 1;
private Context context;
private String TAG = StartActivity.class.getSimpleName();
//----------------------------------------------------
public StartActivity(Context context) {
this.context = context;
}
public void getDataAndSetInRecyclerView(RecyclerView recyclerView) {
loadData(CURRENT_ITEM);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
adapter = new AdapterUser(recyclerView, structList, context);
onLoadMoreListener = new OnLoadMoreListener() {
#Override
public void onLoadMore() {
structList.add(null);
adapter.notifyDataSetChanged();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
structList.remove(structList.size() - 1);
// adapter.notifyItemRemoved(structList.size());
loadData(CURRENT_ITEM);
}
}, 2000);
}
};
adapter.setOnLoadMoreListener(onLoadMoreListener);
recyclerView.setAdapter(adapter);
}
private void loadData(final int CURRENT_ITEM) {
String url = Config.DATA_URL + CURRENT_ITEM;
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
ActivityMain.hideProgressBar();
try {
for (int i = 0; i < response.length(); i++) {
JSONObject jsonObject = response.getJSONObject(i);
StructUser structUser = new StructUser();
if (!jsonObject.isNull(Config.TAG_TITLE))
structUser.setNetworkImageView(jsonObject.getString(Config.TAG_TITLE));
if (!jsonObject.isNull(Config.TAG_IMAGE_URL)) {
structUser.setNetworkImageView(Config.IMG_SERVER + idImage + ".png");
idImage++;
}
structList.add(structUser);
}
adapter.notifyDataSetChanged();
adapter.setLoaded();
// not show progressBar at end of list when get all data
if (response.toString().contains("[]")) {
adapter.reachEndList();
Toast.makeText(context, "not More Data to Show", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// hide progressBar
ActivityMain.hideProgressBar();
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(context,
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest, TAG);
this.CURRENT_ITEM = this.CURRENT_ITEM + LIMIT;
}
}
this is my adapter:
public class AdapterUser extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
public int visibleThreshold = 2;
boolean isLoading;
private int lastVisibleItem, totalItemCount;
private List<StructUser> structList = new ArrayList<>();
private OnLoadMoreListener mOnLoadMoreListener;
private Context context;
// load image from server -------------------------------------------------
private static ImageLoader imageLoader = ImageLoader.getInstance();
public static DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.ic_cloud_download)
.showImageForEmptyUri(R.mipmap.ic_picture)
.showImageOnFail(android.R.drawable.ic_dialog_alert)
.cacheInMemory(true)
.cacheOnDisk(false)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
//---------------------------------------------------------------
public AdapterUser(RecyclerView mRecyclerView, List<StructUser> structList, Context context) {
this.context = context;
this.structList = structList;
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
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 (!isLoading && totalItemCount <= visibleThreshold + (lastVisibleItem)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
}
public void setLoaded() {
isLoading = false;
}
public void reachEndList() {
isLoading = true;
}
//========================================================
#Override
public int getItemViewType(int position) {
return structList.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.adapter_start_activity , viewGroup, false);
return new UserViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_loading_item, viewGroup, false);
return new LoadingViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof UserViewHolder) {
UserViewHolder userViewHolder = (UserViewHolder) holder;
StructUser user = structList.get(position);
userViewHolder.title.setText(user.getTitle());
// load image from server
imageLoader.displayImage(user.getNetworkImageView(), userViewHolder.networkImageView, options);
} else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}
#Override
public int getItemCount() {
return structList == null ? 0 : structList.size();
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener;
}
class UserViewHolder extends RecyclerView.ViewHolder {
public TextView title;
// for download & cash image
public ImageView networkImageView;
public UserViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.txtTitle);
networkImageView = (ImageView) itemView.findViewById(R.id.networkImageView);
}
}
class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar1);
}
}
}
Use Glide for downloading Image...
Glide.with(ActivityName.this)
.load(image_url)
.into(imageView_object);
It will download image and set in ImageView.
I am loading items into a recyclerview from the server using JSON, maintaining an Adapter class to set data by hashmap method. I am using pagination for the recyclerView. Each page contains 10 items and the page increments after 10 items are reached.
The issue is that, after loaded, it's not refreshing when the users click the items.
HomeClass is a launcher activity:
public class HomeClass extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
sendID(url);
}
public void sendID(final String url){
if (progress == null) {
progress = new ProgressDialog(this);
progress.show();
}
Constant.Home_Posts.clear();
new Thread(new Runnable(){
#Override
public void run() {
///pagecount is 1 in HomeClass by default
JSONObject responseObj = new JSONObject(arg0);
HashMap<String, String> map = new HashMap<String, String>();
map.put(key,value);
Constant.Home_Posts.add(map);
}
}
if (progress!=null) {
if (progress.isShowing()) {
progress.dismiss();
progress = null;
Intent intent = new Intent(HomeClass.this, Home.class);
startActivity(intent);
finish();
}
}
The second class, Home, only contais onBindViewHolder
public class Home extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
}
private void getPostCount(final String URl) {
if (progress == null) {
progress = new ProgressDialog(this);
progress.show();
}
new Thread(new Runnable() {
#Override
public void run() {
viewposition = viewposition + 10;
getPostUrl = "url+userid="+ userID+ "&page="+ page_count;
//pagecount is 2 in 'Home' by default and then icrements
JSONObject responseObj = new JSONObject(arg0);
HashMap<String, String> map = new HashMap<String, String>();
map.put(key,value);
Constant.Home_Posts.add(map);
'
'
}
}
}
page_count++;
Adapter Class:
class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public void onBindViewHolder(RecyclerView.ViewHolder holder,final int i) {
if (Constant.Home_Posts.size() - 1 == i) {
Constant.Home_Posts.clear();
getPostCount("url+ userID + "&page=" + page_count);
}
//set value using hashmap method from server
viewHolder.imgComment.setText(value) //with integer values
//OmCLick to update datas from user
viewHolder.imgComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//get layout view by LayoutIflater and load data from server
// create alert dialog
final AlertDialog alertDialog = alertDialogBuilder.create();
//user can comment anyhting,if success comment value in count
//should increment or comments should not change
sendComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (commentStatus == 0) {
} else {
alertDialog.cancel();
String putLikesValue=(Integer.toString(Integer.parseInt(
Constant.Home_Posts.get(i).get("comments_count"))+1));
viewHolder.txtComment.setText(putLikesValue+"Comments");
notifyDataSetChanged();
notifyItemChanged(i);
});
}
The result is like,
the old items are listing with the updated item (newly inserted item).
How do I insert the item with position properly?
Hello use this for load all data.
public FriendsAdapterSwipe(List<FriendListModel> alFriendListModel,RecyclerView recyclerView,Context context)
{
this.alFriendListModel = alFriendListModel;
this.context=context;
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)) {
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
if (viewType == VIEW_ITEM)
{
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.raw_friends_swipe, parent, false);
vh = new CustomViewHolder(itemView);
} else
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
vh = new ProgressViewHolder(v);
}
return vh;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof CustomViewHolder)
{
Typeface AvenirNextRegular = Fonts.AvenirNextRegular(context);
holder.setIsRecyclable(false);
FriendListModel model = alFriendListModel.get(position);
((CustomViewHolder) holder).txtUname.setText(model.getFullName());
((CustomViewHolder) holder).txtUname.setTypeface(AvenirNextRegular);
if (alFriendListModel.get(position).getIsImageAvaible().equalsIgnoreCase("1"))
{
Glide.clear(((CustomViewHolder) holder).imgProfile);
Glide.with(context).load(WebField.PROFILE_URL + alFriendListModel.get(position).getFriendId()
+ "_small.png").asBitmap()
.placeholder(R.drawable.user_pic).skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL).
fitCenter().into(new BitmapImageViewTarget(((CustomViewHolder) holder).imgProfile)
{
#Override
protected void setResource(Bitmap resource)
{
Drawable d = new BitmapDrawable(context.getResources(), resource);
((CustomViewHolder) holder).imgProfile.setImageDrawable(d);
}
});
}
}
else
{
((CustomViewHolder) holder).imgProfile.setImageResource(R.drawable.user_pic);
}
}
#Override
public int getItemCount() {
return alFriendListModel.size();
}
#Override
public int getItemViewType(int position) {
return alFriendListModel.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public static class CustomViewHolder extends RecyclerView.ViewHolder
{
TextView txtUname;
CircularImageView imgProfile;;
public CustomViewHolder(View itemView) {
super(itemView);
txtUname = (TextView) itemView.findViewById(R.id.txtUname);
imgProfile = (CircularImageView) itemView.findViewById(R.id.imgProfile);
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public ProgressViewHolder(View v) {
super(v);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
}
}
public void setLoaded() {
loading = false;
}
You can use loader for set data based on page.
public EventAdapter(final List<EventsModel> myDataSet, RecyclerView recyclerView, Context context) {
mDataset = myDataSet;
this.context = context;
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();
}
loading = true;
}
}
});
}
}
#Override
public int getItemViewType(int position) {
return mDataset.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
if (viewType == VIEW_ITEM) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.raw_eventlist, parent, false);
itemView.setOnClickListener(EventFragment.myOnClickListener);
vh = new TextViewHolder(itemView);
} else {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
vh = new ProgressViewHolder(v);
}
return vh;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof TextViewHolder) {
Typeface AvenirNextRegular = Fonts.AvenirNextRegular(context);
((TextViewHolder) holder).txtEventName.setTypeface(AvenirNextRegular);
((TextViewHolder) holder).txtEventDescription.setTypeface(AvenirNextRegular);
((TextViewHolder) holder).txtDate.setTypeface(AvenirNextRegular);
((TextViewHolder) holder).txtTime.setTypeface(AvenirNextRegular);
((TextViewHolder) holder).txtEventName.setText(mDataset.get(position).getStrEventName());
((TextViewHolder) holder).txtEventDescription.setText(mDataset.get(position).getStrDescription());
((TextViewHolder) holder).txtDate.setText(mDataset.get(position).getStrStartDate());
((TextViewHolder) holder).txtTime.setText(mDataset.get(position).getStrStartTime());
final RecyclerView.ViewHolder tempHolder = holder;
String eventId = mDataset.get(position).getStrEventId();
if (mDataset.get(position).getIsImageAvailable().equalsIgnoreCase("1"))
{
Glide.clear(((TextViewHolder) holder).imgProfile);
Glide.with(context).load(WebField.EVENT_URL + eventId + "_small.png").asBitmap()
.placeholder(R.drawable.event_img).skipMemoryCache(true).
diskCacheStrategy(DiskCacheStrategy.ALL).fitCenter()
.into(new BitmapImageViewTarget(((TextViewHolder) holder).imgProfile) {
#Override
protected void setResource(Bitmap resource) {
Drawable d = new BitmapDrawable(context.getResources(), resource);
((TextViewHolder) tempHolder).imgProfile.setImageDrawable(d);
}
});
}
else
{
((TextViewHolder) holder).imgProfile.setImageResource(R.drawable.event_img);
}
}
}
public void setLoaded() {
loading = false;
}
#Override
public int getItemCount() {
return mDataset.size();
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public static class TextViewHolder extends RecyclerView.ViewHolder {
CircularImageView imgProfile;
TextView txtEventName;
TextView txtEventDescription;
TextView txtDate;
TextView txtTime;
ImageView btnNext;
public TextViewHolder(View view) {
super(view);
this.imgProfile = (CircularImageView) view.findViewById(R.id.imgProfile);
this.txtEventName = (TextView) view.findViewById(R.id.txtEventName);
this.txtEventDescription = (TextView) view.findViewById(R.id.txtEventDescription);
this.txtDate = (TextView) view.findViewById(R.id.txtDate);
this.txtTime = (TextView) view.findViewById(R.id.txtTime);
this.btnNext = (ImageView) view.findViewById(R.id.btnNext);
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public ProgressViewHolder(View v) {
super(v);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
progressBar.getIndeterminateDrawable().setColorFilter(Color.BLUE, PorterDuff.Mode.MULTIPLY);
}
}
I'm trying to add my custom footerView in RecyclerView.I wrote adapter source ,but i can't show my footerView.This is my source
private List<Transaction> transactionList;
public Context mContext;
private boolean loading;
private static final int TYPE_ITEM = 1;
private static final int TYPE_FOOTER = 2;
public void setmOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener;
}
private OnLoadMoreListener mOnLoadMoreListener;
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
public void setLoaded() {
loading = false;
}
class LoadingViewHolder extends RecyclerView.ViewHolder {
public MaterialProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (MaterialProgressBar) itemView.findViewById(R.id.progressBar);
}
}
public class TransactionHolder extends RecyclerView.ViewHolder {
private TextView transactionName, transactionStatus;
public TransactionHolder(View view) {
super(view);
transactionName = (TextView) view.findViewById(R.id.u_transaction_name);
transactionStatus = (TextView) view.findViewById(R.id.u_transaction_status);
}
}
public TransactionRecyclerViewAdapter(List<Transaction> transactions, Context context, RecyclerView recyclerView) {
super();
this.transactionList = transactions;
this.mContext = context;
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)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
}
#Override
public int getItemViewType(int position) {
if (isPositionFooter(position)) {
return TYPE_FOOTER;
}
return TYPE_ITEM;
}
private boolean isPositionFooter(int position) {
return position == transactionList.size();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_FOOTER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_loading, parent, false);
return new TransactionRecyclerViewAdapter.LoadingViewHolder(v);
} else if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_transaction_recycler_item, parent, false);
return new TransactionRecyclerViewAdapter.TransactionHolder(v);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof TransactionHolder) {
TransactionHolder transactionHolder = (TransactionHolder) holder;
Transaction transaction = transactionList.get(position);
if (transaction != null) {
transaction.setAmount(transaction.getAmount().replace("-", ""));
transactionHolder.transactionName.setText(transaction.getName());
transactionHolder.transactionStatus.setText(transaction.getType());
}
} else {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setVisibility(View.VISIBLE);
}
}
#Override
public int getItemCount() {
return transactionList == null ? 0 : transactionList.size();
}
public Transaction getItem(int position) {
return transactionList.get(position);
}
}
and i use my adapter like this
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mTransactionAdapter = new TransactionRecyclerViewAdapter(mTransactionList, getActivity(), mRecyclerView);
mRecyclerView.setAdapter(mTransactionAdapter);
mTransactionAdapter.notifyDataSetChanged();
how i can solve my problem? I don't know what is a wrong in my code
You need to increase count by 1
#Override
public int getItemCount() {
return transactionList == null ? 0 : transactionList.size()+1;
}
#Override
public int getItemCount() {
return transactionList == null ? 0 : transactionList.size();
}
You need to have transactionList.size() + 1 items. (Because you also have a footer).