ViewPager showing data wrong with RecyclerView - android

I am trying to show holidays per year(fetched from web service using volley) and for display holiday I used RecyclerView. Following is my code:
It overall working but some issues exist in this code.
I don't know what I am doing wrong here ?
public class ShowHolidaysPage extends AppCompatActivity implements ViewPager.OnPageChangeListener{
private static final int PAGE_LEFT = 0;
private static final int PAGE_MIDDLE = 1;
private static final int PAGE_RIGHT = 2;
HolidayFragment leftPage = null,middlePage = null,rightPage = null;
List<HolidayFragment> fList = new ArrayList<HolidayFragment>();
enter code here
#Override
protected void onCreate(Bundle savedInstanceState) {
fList.add(HolidayFragment.newInstance("" + (year1 - 1), authToken, deviceId,yearList));
fList.add(HolidayFragment.newInstance("" + year1, authToken, deviceId,yearList));
fList.add(HolidayFragment.newInstance("" + (year1 + 1), authToken, deviceId,yearList));
leftPage = fList.get(PAGE_LEFT);
middlePage = fList.get(PAGE_MIDDLE);
rightPage = fList.get(PAGE_RIGHT);
init();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fList);
pager = (ViewPager)findViewById(R.id.holiday_pager);
pager.setAdapter(pageAdapter);
pager.setOnPageChangeListener(this);
pager.setCurrentItem(1, false);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mSelectedPageIndex = position;
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
final int oldLeftIndex = leftPage.getIndex();
final int oldMiddleIndex = middlePage.getIndex();
final int oldRightIndex = rightPage.getIndex();
if (mSelectedPageIndex == PAGE_LEFT) {
currentYear.add(Calendar.YEAR, -1);
Calendar prevYear = Calendar.getInstance();
prevYear.setTime(currentYear.getTime());
prevYear.add(Calendar.YEAR, -1);
Calendar nextYear = Calendar.getInstance();
nextYear.setTime(currentYear.getTime());
nextYear.add(Calendar.YEAR, 1);
leftPage.setIndex(oldLeftIndex - 1, prevYear);
middlePage.setIndex(oldLeftIndex, currentYear);
rightPage.setIndex(oldMiddleIndex, nextYear);
}
else if (mSelectedPageIndex == PAGE_RIGHT) {
currentYear.add(Calendar.YEAR, 1);
Calendar prevYear = Calendar.getInstance();
prevYear.setTime(currentYear.getTime());
prevYear.add(Calendar.YEAR, -1);
Calendar nextYear = Calendar.getInstance();
nextYear.setTime(currentYear.getTime());
nextYear.add(Calendar.YEAR, 1);
leftPage.setIndex(oldMiddleIndex, prevYear);
middlePage.setIndex(oldRightIndex, currentYear);
rightPage.setIndex(oldRightIndex + 1, nextYear);
}
pager.setCurrentItem(1, false);
}
}
class MyPageAdapter extends FragmentStatePagerAdapter {
private List<HolidayFragment> fragments;
public MyPageAdapter(FragmentManager fm, List<HolidayFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
}
this method is in holiday fragment:
public void setIndex(int index,Calendar year1) {
this.index = index;
if(year1 != null) {
year = ""+year1.get(Calendar.YEAR);
if(year.equals(""+year1.get(Calendar.YEAR))) {
String year = "" + year1.get(Calendar.YEAR);
yearView.setText(year);
if(networkCall.getRequestQueue()!= null) {
networkCall.getRequestQueue().cancelAll(getTag());
}
getHolidays(authtoken, deviceId, yearView.getText().toString());
}
}
}
public void getHolidays(String authToken, String deviceID, final String year) {
if(recyclerView != null) {
if (recyclerView.getVisibility() == View.VISIBLE) {
recyclerView.setVisibility(View.GONE);
}
}
if(holidayNotAvailable != null) {
if (holidayNotAvailable.getVisibility() == View.VISIBLE) {
holidayNotAvailable.setVisibility(View.GONE);
}
}
if(yearList==null){
yearList=new ArrayList<Integer>();
}
if(!yearList.contains(Integer.parseInt(year))) {
progressbar.setVisibility(View.VISIBLE);
networkCall = NetworkCall.getInstance(getActivity().getApplicationContext());
String url = url;
url += "&year=" + year;
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
yearList.add(Integer.parseInt(year));
try {
Map<String, String> holidaysMap = new Gson().fromJson(jsonObject + "", new TypeToken<SortedMap<String, String>>() {
}.getType());
progressbar.setVisibility(View.GONE);
if (holidaysMap.size() != 0) {
if (holidayNotAvailable.getVisibility() == View.VISIBLE) {
holidayNotAvailable.setVisibility(View.GONE);
}
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setVisibility(View.VISIBLE);
recyclerView.setLayoutManager(layoutManager);
adapter = new HolidayAdapter(holidaysMap, year);
recyclerView.setAdapter(adapter);
} else {
progressbar.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
holidayNotAvailable.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
String msg = "";
if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {
msg = "Time out Error! Please try again later";
} else if (volleyError instanceof AuthFailureError) {
startActivity(new Intent(getActivity().getApplicationContext(), IntroActivity.class));
} else if (volleyError instanceof ServerError) {
msg = "Server Error! Please try again later";
} else if (volleyError instanceof NetworkError) {
msg = "Network Error! Please try again later";
} else if (volleyError instanceof ParseError) {
msg = "Parser Error! Please try again later";
}
if (!EwUtils.isNullString(msg)) {
if (getActivity() != null) {
Toast.makeText(getActivity().getApplicationContext(), msg, Toast.LENGTH_SHORT);
}
}
}
});
networkCall.addToRequestQueue(jsonObject);
}
}
Its shows pages on swipe left or right correctly but following two issues are exist there now:
Three pages forms at a time so when we swipe left or right it again call the get holiday method which create view while it is already created, So I am unable to know why it recreate the page.
when we swipe fast then it shows data wrong.It seems it puts data of another request in another fragment.
I already tried it by using pager.setOffscreenPageLimit(1); but is not works and recreate the fragment when it comes to idle state.
I don't know what I am doing wrong here.So please guide me about this.

By default, your ViewPager retains one page left and one page right from the active (current) fragment.
This is, when you go to the third the first is destroyed and the fouth is created like a cache for a better user experience.
You can change your limit calling the method of ViewPager setOffscreenPageLimit
Regarding to your wrong data: I recommend you to separate the logic in different instances from this class. The problem is that the requests are made asynchronously so you change the page before having the response back and it seems to be messy calling the same piece of code.
I hope this would help you

Related

How to fix Recyclerview returns same items android

i checked a lot of questions to fix my issue but no success also this will fix a 3 issues for me, a big ones!
I'm parsing my YouTube videos using Gson and Retrofit and it showed successfully but after last results it returns the same items over and over.
Here i call my function used to parse videos..
// NestedScrollView used instead of using
// RecyclerView as NestedScrollView disables
// scroll listeners of recycler so, we use nested.
NestedScrollView nestedScrollView = findViewById(R.id.nested_scrollview);
nestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
if ((scrollY >= (v.getChildAt(v.getChildCount() - 1).getMeasuredHeight() - v.getMeasuredHeight())) && scrollY > oldScrollY) {
getJson();
}
});
if (videoList.size() == 0) {
getJson();
}
}
And here is my getJson which parse my videos...
// Get Json Data
private void getJson() {
shimmer.setVisibility(View.VISIBLE);
// Parsed Url
String url = YoutubeAPI.BASE_URL + YoutubeAPI.SEARCH + YoutubeAPI.KEY + YoutubeAPI.CHANNNEL_ID + YoutubeAPI.ORDER + YoutubeAPI.MAX_RESULTS + YoutubeAPI.PART;
if (!nextPageToken.equals("")) {
// Add page token to new url
url += (YoutubeAPI.NEXT_PAGE_TOKEN + nextPageToken);
shimmer.setVisibility(View.GONE);
}
if (nextPageToken == null) {
return;
}
Call<YoutubeMain> data = YoutubeAPI.getMainVideo().getYoutube(url);
data.enqueue(new Callback<YoutubeMain>() {
#Override
public void onResponse(Call<YoutubeMain> call, Response<YoutubeMain> response) {
if (response.errorBody() != null) {
Log.v("TAG", "onResponse: " + response.errorBody());
shimmer.setVisibility(View.GONE);
// Print error code
Toast.makeText(YoutubeActivity.this, response.errorBody().toString(), Toast.LENGTH_SHORT).show();
} else {
YoutubeMain youtubeMain = response.body();
assert youtubeMain != null;
videoList.addAll(youtubeMain.getItems());
adapter.notifyDataSetChanged();
shimmer.setVisibility(View.GONE);
// Get nextPageToken to assign it to new url
if (youtubeMain.getNextPageToken() != null) {
nextPageToken = youtubeMain.getNextPageToken();
}
// Get creatorName to assign it to author
if (youtubeMain.getItems().get(0).getSnippet().getChannelTitle() != null) {
author.setText(youtubeMain.getItems().get(0).getSnippet().getChannelTitle());
}
}
}
#Override
public void onFailure(Call<YoutubeMain> call, Throwable t) {
shimmer.setVisibility(View.GONE);
// Print error code
Toast.makeText(YoutubeActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
this is my adapter...
public class YoutubeMainAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<YoutubeVideo> videoList;
private final OnYoutubeItemClickListener listener;
private String formatted_date;
public YoutubeMainAdapter(Context context, List<YoutubeVideo> videoList, OnYoutubeItemClickListener listener) {
this.videoList = videoList;
this.listener = listener;
}
class YoutubeHolder extends RecyclerView.ViewHolder {
ImageView thumbnail;
TextView title, description, publishedAt;
YoutubeHolder(#NonNull View itemView) {
super(itemView);
thumbnail = itemView.findViewById(R.id.ImageThumb);
title = itemView.findViewById(R.id.textViewTitle);
description = itemView.findViewById(R.id.textViewDes);
publishedAt = itemView.findViewById(R.id.textViewDate);
}
public void setData(YoutubeVideo data) {
String getTitle = data.getSnippet().getTitle();
String getDescription = data.getSnippet().getDescription();
String getPublishedAt = format_date(data.getSnippet().getPublishedAt());
String getThumbnail = data.getSnippet().getThumbnails().getHigh().getUrl();
title.setText(getTitle);
description.setText(getDescription);
publishedAt.setText(getPublishedAt);
Picasso.get()
.load(getThumbnail)
.into(thumbnail);
}
void bind(final YoutubeVideo item, final OnYoutubeItemClickListener listener) {
itemView.setOnClickListener(v -> listener.onItemClick(item));
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_youtube_listitem, parent, false);
return new YoutubeHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
YoutubeVideo youtubeVideo = videoList.get(position);
YoutubeHolder youtubeHolder = (YoutubeHolder) holder;
youtubeHolder.setData(youtubeVideo);
youtubeHolder.bind(videoList.get(position), listener);
}
private String format_date(String publishedAt) {
try {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
#SuppressLint("SimpleDateFormat") SimpleDateFormat format = new SimpleDateFormat("dd, MMM yyyy • hh:mm a");
Date date = dateFormat.parse(publishedAt);
assert date != null;
formatted_date = format.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
return formatted_date;
}
#Override
public int getItemCount() {
return videoList.size();
}
}
I tried many times to fix it but no success and after checking some questions related to this issues, all answers was for (for loop) with regular Json parsing and no Gson. thanks in advance and i appreciate help.
Your adapter is correct.
Since you noted: after last results it returns the same items over and over. thats because nextPageToken will return null in the last time and you keep the last reference if (youtubeMain.getNextPageToken() != null) nextPageToken = youtubeMain.getNextPageToken();
You need a condition to stop requesting new pages

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder

So many people have faced this exception and i tried the solutions available for this exception but none of it actually worked for my case.
So my problem is i have a filter button at my toolbar and it has three items in it 1. ascending order , 2. descending order , 3. date specific. when i am selecting ascending and descending items data is getting populated correctly inside recyclerview. but when i am selecting the date specific option and showing a datepicker ....the data is not getting populated inside recyclerview and when i touch screen application gets crashed and gives me the above mentioned exception.
my code for fragment where i am performing these operations :-
public class PendingOrders extends Fragment {
String filterString="date_desc";
String filterDateString="";
private int mDay,mMonth,mYear;
private static final String TAG = "PendingORDERS";
private RecyclerView mMessagesView;
private List<PendingOrderModel> mMessages = new ArrayList<PendingOrderModel>();
CustomItemClickListener listener;
private PendingOrderAdapter mAdapter;
private Socket mSocket;
private Boolean isConnected = true;
public static final int DIALOG_FRAGMENT = 1;
String actualPrice,amount,total,filledAmount,orderPrice,proceeds,orderDate,orderType,orderId;
String currencyname,order,order1,orderType1 , orderDate1,idz;
public PendingOrders() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mAdapter = new PendingOrderAdapter(context, mMessages,listener);
if (context instanceof Activity) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
AppController app = (AppController) getActivity().getApplication();
SharedPreferences pref = getActivity().getSharedPreferences("MyPREFERENCES", 0);
idz=pref.getString("ZuserID", null);
mSocket = app.getSocket();
mSocket.on("pending_orders_data", orderCompletedData);
mSocket.connect();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_pending_orders, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMessagesView = (RecyclerView) view.findViewById(R.id.rv_pending_orders);
mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity()));
mMessagesView.setItemAnimator(null);
mAdapter = new PendingOrderAdapter(getActivity(), mMessages, new CustomItemClickListener() {
#Override
public void onItemClick(View v, int position) {
String orderid = mMessages.get(position).getmOrderId();
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
Fragment prev = getActivity().getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFrag = PendingCancelDialog.newInstance(123);
dialogFrag.show(getActivity().getFragmentManager().beginTransaction(), "dialog");
Bundle args = new Bundle();
args.putString("ID",orderid);
dialogFrag.setArguments(args);
}
});
mMessagesView.setAdapter(mAdapter);
initObjects();
}
private void initObjects() {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("user_id", idz);
} catch (JSONException e) {
e.printStackTrace();
}
mSocket.emit("register_user", jsonObject.toString());
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
}
public String getSendMessageString(String message) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("page_no", "1"); //1: text message 2: multimedia message
jsonObject.put("user_id", idz);
jsonObject.put("records_per_page", "5");
jsonObject.put("filter", filterString);
Log.i("??", "filterString: "+filterString);
jsonObject.put("filter_date", filterDateString);
Log.i("??", "filterDateString: "+filterDateString);
return jsonObject.toString();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
private void addMessage(String orderId,String order,String currencyname,String amount,String filledAmount,String proceeds,String orderPrice,String orderDate,String orderType) {
mMessages.add(new PendingOrderModel.Builder(PendingOrderModel.RECEIVER)
.orderid(orderId).order(order).amount(amount).currencyname(currencyname).filledamount(filledAmount).orderprice(orderPrice).proceeds(proceeds).orderdate(orderDate).ordertype(orderType).build());
mMessagesView.getRecycledViewPool().clear();
mAdapter.notifyDataSetChanged();
}
private Emitter.Listener orderCompletedData = new Emitter.Listener() {
#Override
public void call(final Object... args) {
if(getActivity() != null) {
getActivity().runOnUiThread(() -> {
JSONArray object1 = (JSONArray) args[0];
if(object1 != null){
JSONArray array = new JSONArray();
array = object1.optJSONArray(0);
int arraylength = array.length();
for(int j=0; j<array.length();j++){
JSONObject obj = new JSONObject();
try {
obj = array.getJSONObject(j);
currencyname = obj.getString("coin");
orderId = obj.getString("id");
order1 = obj.getString("order");
filledAmount = obj.getString("coin_quantity");
amount = obj.getString("total_amount");
proceeds = obj.getString("remaining");
orderPrice = obj.getString("order_price");
orderDate1 = obj.getString("create_time");
orderType1= obj.getString("order_type");
} catch (JSONException e) {
e.printStackTrace();
}
if(order1 == "1"){
order = "Limit";
}
else{
order = "Market";
}
if(orderType1 == "1"){
orderType = "Sell";
}else{
orderType = "buy";
}
String [] date = orderDate1.split("T");
orderDate = date[0].trim();
addMessage(orderId,order,currencyname,amount,filledAmount,proceeds,orderPrice,orderDate,orderType);
}
}
});
}
}
};
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.asc_order:
filterString="date asc";
filterDateString="";
mMessages.clear();
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
return true;
case R.id.desc_order:
filterString="date desc";
mMessages.clear();
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
return true;
case R.id.pick_date:
filterString="date specific";
mMessages.clear();
pickdate();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void pickdate() {
Calendar c1 = Calendar.getInstance();
mYear = c1.get(Calendar.YEAR);
mMonth = c1.get(Calendar.MONTH);
mDay = c1.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(),R.style.DAte_Theme,
(view, year, monthOfYear, dayOfMonth) -> {
int month = monthOfYear + 1;
String formattedMonth = "" + month;
String formattedDayOfMonth = "" + dayOfMonth;
if(month < 10){
formattedMonth = "0" + month;
}
if(dayOfMonth < 10){
formattedDayOfMonth = "0" + dayOfMonth;
}
filterDateString= formattedDayOfMonth + "/" + formattedMonth + "/" + year;
Log.i("date",filterDateString);
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
// updateDate(filterDateString);
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
}
Below is my Logcat :-
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{cfdb59c position=3 id=-1, oldPos=-1, pLpos:-1 no parent} android.support.v7.widget.RecyclerView{476168c VFED..... .F...... 0,0-1080,1560 #7f090169 app:id/rv_pending_orders}, adapter:com.vamediabox.greenpay.adapters.PendingOrderAdapter#d6e71d5, layout:android.support.v7.widget.LinearLayoutManager#e738dea, context:com.vamediabox.greenpay.activities.MyorderActivity#70a64f9
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5421)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5603)
at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:285)
at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:342)
at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:358)
at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:365)
at android.support.v7.widget.GapWorker.run(GapWorker.java:396)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
See just do one thing when you select the date picker then add these lines before calling the main function.
onClick
{
adapter.notifyDataSetChanged();
recyclerView.getRecycledViewPool().clear();
and then the rest code....
}

Recyclerview Inconsistency detected. Invalid view holder adapter positionViewHolder

In my app right now I am working with two lists. One is a List of an Object and the other the a List of Lists of the same object. I have a method in my Activity that transforms a list of Object into a List of Lists of object. And to my adapter I am passing the list of lists through this call:
mAdapter.swap(transformList(pipe.mList));
The method swap is responsible for passing the transformed list to my Adapter:
public void swap(List<List<Feed>> feedList) {
if (finallist == null) {
finallist = new ArrayList<>();
}
finallist.clear();
finallist.addAll(feedList);
}
The transformation checks if there are images in a row and puts all of them inside a single list (I am trying to implement something similar to WhatsApp image grouping). So I have a bunch of messages, they can be text messages, files, images, etc. In case of the last one, I group them in a single list.
Let me give a scenario as an example:
I have four images and 1 text message in my original array. The transformation puts all the four images into a single List of objects and de text message in another list of objects (both of them are inserted in my list of lists).
I thought about two ways to handle this transformation: 1 - do it inside the Adapter and 2 - do it in my Activity and pass the modified list to the Adapter. Each one of this solutions generated a different problem.
By following the steps in 1, I was able to display all of the content almost in the way I wanted. The grouping was working just fine! The problem is that if the original array had a length equals to 30, and the transformed array's length was decreased to 12. The RecyclerView would show all of the remaining 18 items as empty states (so after the transformation it wasn't handling the removing items properly).
By following the steps in 2, I was not able to display all of the content. Just the first element of my array. And I would get a IndexOutOfBoundsException in RecyclerView happens java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder error message. But I was not able to identify the problem. I checked many questions here and none of them helped me.
This is my Adapter class:
public class FeedAdapter extends BaseSkeletonAdapter<Feed> implements FeedHolder.FeedHolderListener{
private static final int HOLDER_COMMENT = 1;
private static final int HOLDER_IMAGE = 2;
private static final int HOLDER_FILE = 3;
private static final int HOLDER_AUDIO = 4;
private static final int HOLDER_MARKER = 5;
private static final int HOLDER_EMPTY = 6;
private static final int HOLDER_GROUP = 7;
private final FeedItemListener mListener;
private final int mAvatarSize;
private final String mUserId;
private final int mPictureSize;
private final int mSkeletonColor;
public static List<List<Feed>> finallist;
public FeedAdapter(FeedItemListener listener, String userId, int avatarSize, int pictureSize, int skeletonColor) {
super(2);
mListener = listener;
mUserId = userId;
mAvatarSize = avatarSize;
mPictureSize = pictureSize;
mSkeletonColor = skeletonColor;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case HOLDER_COMMENT:
case HOLDER_IMAGE:
case HOLDER_FILE:
case HOLDER_MARKER:
case HOLDER_AUDIO:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_feed, parent, false);
return new FeedHolder(view, this, mPictureSize);
case HOLDER_GROUP:
System.out.println("É um grupo!!!");
View viewGroup = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_feed_group,parent,false);
return new FeedHolder(viewGroup, this, mPictureSize);
case HOLDER_EMPTY:
default:
View empty = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_empty, parent, false);
return new EmptyPlaceholderViewHolder(empty, R.string.placeholder_feed_empty_title, R.string.placeholder_feed_empty_description, R.drawable.ic_feed_placeholder);
}
}
#Override
protected void onBind(RecyclerView.ViewHolder holder, int position) {
if(!(holder instanceof EmptyPlaceholderViewHolder)){
//Feed feed = finallist.get(position).get(0);
if (holder instanceof FeedHolder) {
if (position < finallist.size()) {
if (mUserId.equals(finallist.get(position).get(0).getCreatedById())) {
((FeedHolder) holder).onBind(finallist.get(position), mUserId, mAvatarSize);
} else {
((FeedHolder) holder).onBind(finallist.get(position), mUserId, mAvatarSize);
}
}
}
}
}
#Override
protected void onBind(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
}else {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).onBind(finallist.get(position), payloads, mUserId, mAvatarSize);
}
}
}
#Override
protected void setHolderSkeleton(RecyclerView.ViewHolder holder) {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).setHolderSkeleton(R.drawable.rounded_skeleton, mSkeletonColor);
}
}
#Override
protected void clearHolderSkeleton(RecyclerView.ViewHolder holder) {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).clearHolderSkeleton();
}
}
#Override
public int getItemViewType(int position) {
if(mSkeletonMode){
return HOLDER_COMMENT;
} if (finallist != null && finallist.size() > 0 && position >= 0 && position < finallist.size()) {
System.out.println("Tamanho total: " + finallist.size());
if (finallist.get(position).size() > 1) {
System.out.println("Tamanho do grupo: " + finallist.get(position).size());
return HOLDER_GROUP;
} else {
Feed feed = finallist.get(position).get(0);
if (feed != null) {
String type = feed.getFeedType();
if (type != null) {
switch (type) {
case FEED_IMAGE:
return HOLDER_IMAGE;
case FEED_AUDIO:
return HOLDER_AUDIO;
case FEED_FILE:
return HOLDER_FILE;
case FEED_MARKER:
return HOLDER_MARKER;
case FEED_COMMENT:
default:
return HOLDER_COMMENT;
}
}
}
}
return HOLDER_COMMENT;
}else {
System.out.println("Tá vazia!");
return HOLDER_EMPTY;
}
}
public List<Feed> getItems() {
return returnList(finallist);
}
public List<List<Feed>> getListItems() {
return finallist;
}
public void swap(List<List<Feed>> feedList) {
if (finallist == null) {
finallist = new ArrayList<>();
}
finallist.clear();
finallist.addAll(feedList);
}
#Override
public void toggleLike(final int pos){
if(mListener != null && pos >= 0 && pos < finallist.size()){
mListener.toggleLike(finallist.get(pos).get(0));
}
}
#Override
public void onLongClick(final int pos, final View v) {
if (mListener != null && pos >= 0 && pos < finallist.size()) {
mListener.onLongClick(finallist.get(pos).get(0), v);
}
}
#Override
public int onAudioActionClicked(final int pos, final int progress) {
if (mListener != null) {
return mListener.onAudioActionClicked(pos, finallist.get(pos).get(0), progress);
}else {
return 0;
}
}
#Override
public void onClick(int pos) {
if (finallist!=null && pos >= 0 && pos<finallist.size()) {
Feed feed = finallist.get(pos).get(0);
if (feed != null && mListener != null) {
mListener.onClick(feed);
}
}
}
public interface FeedItemListener {
void toggleLike(#NonNull Feed feed);
void onLongClick(#NonNull Feed feed, #NonNull View v);
void onClick(#NonNull Feed feed);
int onAudioActionClicked(int pos, #NonNull Feed feed, final int progress);
}
private void transformList(List<Feed> mItems) {
finallist = new ArrayList<>();
for (int i = 0; i< mItems.size();i++) {
List<Feed> feed = new ArrayList<>();
feed.add(mItems.get(i));
finallist.add(feed);
}
int j = 0;
List<String> list = new ArrayList<>();
List<Integer> indexList = new ArrayList<>();
//System.out.println("Tamanho: " + mItems.size());
for (int i = 0; i < mItems.size(); i++) {
if (!mItems.get(i).getFeedType().equals("filePicture")) {
if (j >= 4) {
String temp = "";
for (int k = 0; k < j; k++) {
temp = temp + "->" + Integer.toString(i - (k+1));
if (k != 0) {
finallist.get(i - 1).add(finallist.get(i - (k + 1)).get(0));
indexList.add(i - (k+1));
}
}
list.add(temp);
}
j = 0;
} else {
j = j + 1;
}
if (i == mItems.size()-1) {
//System.out.println("Imagem por ultimo!");
if (j >= 4) {
//System.out.println("Grupo vem por ultimo!");
String temp = "";
for (int k = 0; k < j; k++) {
temp = temp + "->" + Integer.toString(i - (k));
if (k != 0) {
finallist.get(i).add(finallist.get(i - (k)).get(0));
indexList.add(i - (k));
}
}
list.add(temp);
}
}
}
Collections.sort(indexList);
int aux = 0;
for (int i = 0; i < indexList.size();i++) {
//System.out.println("Valor da posição: " + indexList.get(i)+ "\nTipo: "+ finallist.get((indexList.get(i).intValue())+aux).get(0).getFeedType()
// +"\nValor da posição + i: " + (indexList.get(i)+aux) + "\nAux: " + aux);
finallist.remove((indexList.get(i).intValue())+aux);
//notifyItemRangeRemoved(0, finallist.size());
//notifyDataSetChanged();
aux = aux - 1;
}
/*for (int i = 0; i< finallist.size(); i++){
if (finallist.get(i).size() > 1) {
System.out.println("groupImage: " + finallist.get(i).size());
} else {
System.out.println(finallist.get(i).get(0).getFeedType());
}
}*/
//returnList(finallist);
notifyItemRangeRemoved(0, returnList(finallist).size() - finallist.size() - 1);
//notifyItemRangeInserted(0, finallist.size());
}
public List<Feed> returnList(List<List<Feed>> lists) {
List<Feed> list = new ArrayList<>();
if (lists != null) {
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).size() > 1) {
for (int j = 0; j < lists.get(i).size(); j++) {
list.add(lists.get(i).get(j));
}
} else {
list.add(lists.get(i).get(0));
}
}
System.out.println("Tamanho de list: " + list.size());
}
return list;
}
}
And this is my Activity:
public abstract class FeedActivity extends UltraBaseActivity implements FeedAdapter.FeedItemListener, AudioManager.OnAudioFocusChangeListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
private static final String EXTRA_PROJECT_ID = "extra_project_id";
private static final String EXTRA_PROJECT_NAME = "extra_project_name";
private static final String EXTRA_RESOURCE_ID = "extra_resource_id";
private static final String EXTRA_RESOURCE_NAME = "extra_resource_name";
private static final String EXTRA_RESOURCE_KIND = "extra_resource_kind";
#BindView(R.id.swipeLayout) SwipeRefreshLayout mRefreshLayout;
#BindView(R.id.recyclerView) RecyclerView mRecyclerView;
#BindView(R.id.feedCreateFragment) View mFeedCreateLayout;
#BindView(R.id.mic) ImageView mMicView;
private WeakReference<FeedCreateFragment> mFeedCreateFragment;
protected FeedViewModel mViewModel;
protected FeedAdapter mAdapter;
private Feed mLongClick;
private Toolbar mToolbar;
protected int mScrollTo = -1;
protected WrapContentLinearLayoutManager mLayoutManager;
private String mPlayingFeedId;
private int mPlayingPos;
private int mActionResourcePause = R.drawable.ic_pause_black_24dp;
private int mActionResourcePlay = R.drawable.ic_play_black_24dp;
private MediaPlayer mPlayer;
private AudioManager mAudioManager;
protected Handler mAudioHandler;
protected Runnable mUpdateAudioHolderRunnable = new Runnable() {
#Override
public void run() {
try {
if (mPlayer != null && mPlayer.isPlaying()) {
notifyAdapterAudioUpdate(mPlayer.getCurrentPosition(), mActionResourcePause);
mAudioHandler.postDelayed(this, 100);
} else {
mAudioHandler.removeCallbacks(mUpdateAudioHolderRunnable);
}
} catch (IllegalStateException e){
MyLog.e(TAG, "Error while updating seed bar", e);
mAudioHandler.removeCallbacks(mUpdateAudioHolderRunnable);
}
}
};
public static void start(#NonNull Context context, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind){
Intent intent = setIntent(context, projectId, projectName, resourceId, resourceName, resourceKind);
if (intent == null) return;
context.startActivity(intent);
}
public static void startForResult(#NonNull Fragment fragment, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind){
Intent intent = setIntent(fragment.getContext(), projectId, projectName, resourceId, resourceName, resourceKind);
if (intent == null) return;
fragment.startActivityForResult(intent, Constants.Intents.INTENT_REQUEST_VIEW_FEED);
}
#Nullable
protected static Intent setIntent(#NonNull Context context, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind) {
Intent intent;
if (resourceKind.equals(Task.ROUTE)) {
intent = new Intent(context, FeedTaskActivity.class);
}else if(resourceKind.equals(Chat.ROUTE)){
intent = new Intent(context, FeedChatActivity.class);
} else {
MyLog.e(TAG, "Error invalid resource Kind - " + resourceKind);
return null;
}
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_PROJECT_NAME, projectName);
intent.putExtra(EXTRA_RESOURCE_ID, resourceId);
intent.putExtra(EXTRA_RESOURCE_NAME, resourceName);
intent.putExtra(EXTRA_RESOURCE_KIND, resourceKind);
return intent;
}
public FeedActivity() {
super(R.layout.activity_feed);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
isLogged();
init(getIntent(), savedInstanceState);
super.onCreate(savedInstanceState);
initAdapter();
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mAudioHandler = new Handler();
mViewModel.subscribe()
.compose(this.<Resource<List<Feed>>>bindUntilEvent(ActivityEvent.DESTROY))
.flatMap(flatMapDiffUtils())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onNext(), onError(), onCompleted());
}
#NonNull
private Func1<Resource<List<Feed>>, Observable<FeedViewModel.Pipe>> flatMapDiffUtils() {
return new Func1<Resource<List<Feed>>, Observable<FeedViewModel.Pipe>>() {
#Override
public Observable<FeedViewModel.Pipe> call(Resource<List<Feed>> r) {
if (mViewModel.hasResource()) {
List<Feed> old = mAdapter.getItems();
MyLog.i(TAG, "New length: " + (r.data != null ? r.data.size() : 0) + " - Old: " + old.size());
final FeedDiffCallback cb = new FeedDiffCallback(old, r.data, mUser.getId());
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(cb);
return Observable.just(new FeedViewModel.Pipe(r.data, result, r.status == Status.LOADING && (r.data ==null || r.data.size() == 0)));
} else {
MyLog.i(TAG, "Loading resource from server");
return Observable.empty();
}
}
};
}
private Action1<? super FeedViewModel.Pipe> onNext() {
return new Action1<FeedViewModel.Pipe>() {
#Override
public void call(FeedViewModel.Pipe pipe) {
if (pipe != null) {
initFeedFragment();
mRefreshLayout.setRefreshing(false);
pipe.mDiffResult.dispatchUpdatesTo(mAdapter);
mAdapter.setSkeletonMode(pipe.mSkeletonMode);
//List<List<Feed>> list = new ArrayList<>();
//list = tranformList(pipe.mList);
mAdapter.swap(transformList(pipe.mList));
System.out.println("Tamanho desse troço: " + transformList(pipe.mList).size());
//mAdapter.notifyDataSetChanged();
//mAdapter.notifyItemRangeRemoved(0, pipe.mList.size());
if (mScrollTo == -1) {
mRecyclerView.scrollToPosition(mAdapter.getItemCount()-1);
}else {
mRecyclerView.scrollToPosition(mScrollTo);
}
updateMenuOptions();
showLoading(false);
}
}
};
}
protected Action0 onCompleted() {
return new Action0() {
#Override
public void call() {
MyLog.i(TAG, "Finishing feed activity");
finish();
}
};
}
protected Action1<Throwable> onError() {
return new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
MyLog.e(TAG, "Error", throwable);
}
};
}
#Override
protected void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if(mToolbar !=null) {
if (mViewModel != null) {
mToolbar.setTitle(mViewModel.getProjectName());
mToolbar.setSubtitle(mViewModel.getResourceName());
}
mToolbar.setSubtitleTextColor(ContextCompat.getColor(this, R.color.palette_black));
mToolbar.setNavigationIcon(R.drawable.ic_action_back_black);
}
setSupportActionBar(mToolbar);
if (mToolbar != null) {
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
}
}
protected void updateTitle(){
if(mToolbar !=null && mViewModel != null) {
mToolbar.setTitle(mViewModel.getProjectName());
mToolbar.setSubtitle(mViewModel.getResourceName());
}
}
#Override
protected void userUpdated(User user) { }
private void init(Intent i, Bundle b){
if (i != null) {
initViewModel(
i.getStringExtra(EXTRA_PROJECT_ID),
i.getStringExtra(EXTRA_PROJECT_NAME),
i.getStringExtra(EXTRA_RESOURCE_ID),
i.getStringExtra(EXTRA_RESOURCE_NAME),
i.getStringExtra(EXTRA_RESOURCE_KIND));
}else if(b != null){
initViewModel(
b.getString(EXTRA_PROJECT_ID),
b.getString(EXTRA_PROJECT_NAME),
b.getString(EXTRA_RESOURCE_ID),
b.getString(EXTRA_RESOURCE_NAME),
b.getString(EXTRA_RESOURCE_KIND));
}else {
MyLog.i(TAG, "Error while initializing view model");
finish();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(EXTRA_PROJECT_ID, mViewModel.getProjectId());
outState.putString(EXTRA_PROJECT_NAME, mViewModel.getProjectName());
outState.putString(EXTRA_RESOURCE_ID, mViewModel.getResourceId());
outState.putString(EXTRA_RESOURCE_NAME, mViewModel.getResourceName());
outState.putString(EXTRA_RESOURCE_KIND, mViewModel.getResourceKind());
}
private void initAdapter(){
mAdapter = new FeedAdapter(
this,
mUser.getId(),
getResources().getDimensionPixelSize(R.dimen.task_avatar_size),
(int) (AndroidUtils.getScreenWidth(this) * 0.6),
ContextCompat.getColor(this, R.color.bg_skeleton)
);
mRefreshLayout.setColorSchemeResources(R.color.yellow, android.R.color.darker_gray, R.color.yellow_edit_note, android.R.color.background_dark);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mScrollTo = -1;
mViewModel.reload();
}
});
mLayoutManager = new WrapContentLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
private void initFeedFragment(){
if(!(mFeedCreateFragment != null && mFeedCreateFragment.get() != null && getSupportFragmentManager().findFragmentById(R.id.feedCreateFragment) instanceof FeedCreateFragment)){
mFeedCreateFragment = new WeakReference<>(FeedCreateFragment.newInstance(mViewModel.getProjectId(), mViewModel.getResourceId(), mViewModel.getResourceKind(), mViewModel.getResourceUsers()));
getSupportFragmentManager()
.beginTransaction()
.add(R.id.feedCreateFragment, mFeedCreateFragment.get())
.commitAllowingStateLoss();
if (mViewModel.canCreateFeed()) {
mFeedCreateLayout.setVisibility(View.VISIBLE);
}else {
mFeedCreateLayout.setVisibility(View.GONE);
}
}
}
protected abstract void initViewModel(String projectId, String projectName, String resourceId, String resourceName, String resourceKind);
protected abstract void updateMenuOptions();
}
This is part of the Error (the text reached the maximum size):
10-18 17:29:14.702 23722-23722/com.construct.test E/WrapContentLinearLayoutManager: IndexOutOfBoundsException in RecyclerView happens
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{615b449 position=3 id=-1, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5297)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5479)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
at com.construct.v2.adapters.WrapContentLinearLayoutManager.onLayoutChildren(WrapContentLinearLayoutManager.java:20)
My problem was caused by the BaseSkeletonAdapter<Feed> that my FeedAdapter was extending. BaseSkeletonAdapter was using the original list and not the List of Lists I had to use. So I created a new class SkeletonAdapterFeed that is basically equal to the previous one, but the new one is receiving a List of Lists instead of just the List.
I know that it sounds a little confusing. I don't have full understanding of the project I am working right now so that's why I don't know everything about the classes, etc.

RecyclerView already scrolled to bottom when activity starts

I have fragments with RecyclerView in my activity, But whenever I start the fragment, the RecyclerView is already scrolled to the bottom. To load more item, user have to scroll a little bit upwards and then scroll back to the bottom, And when more items load, RecyclerView is again scrolled to the new bottom.
Here is the code in fragment.
public class FavouriteFragment extends Fragment{
public RecyclerView recyclerView ;
public RecyclerView.Adapter adapter ;
public LinearLayoutManager layoutManager ;
int pastVisiblesItems, visibleItemCount, totalItemCount;
Constants constants;
ArrayList<CardSetterGetter> arrayList;
private List<CardSetterGetter> imagelist;
int start ;
public int end ;
boolean loading = true ;
int totalcount ;
ArrayList<String> imageNameArray ;
String androidId;
String categoryName ;
String cateGoryFlag = "false";
String url;
String tagname = "";
ArrayList<String> title ;
ProgressBar progressBar ;
TextView errormsg ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//to hide search
setHasOptionsMenu(true);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.search);
item.setVisible(false);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.favourite_fragment,container,false);
arrayList = new ArrayList<CardSetterGetter>();
imageNameArray = new ArrayList<String>();
start = 0;
end = start + 2 ;
imagelist = new ArrayList<CardSetterGetter>();
recyclerView = (RecyclerView)view.findViewById(R.id.recyclerview);
progressBar = (ProgressBar)view.findViewById(R.id.progressBar);
errormsg = (TextView) view.findViewById(R.id.error);
getdata();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if(dy > 0)
{
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
int i = visibleItemCount + pastVisiblesItems ;
System.out.println(i);
System.out.println(totalItemCount);
if(loading) {
if (i == totalItemCount) {
loading = false ;
start = arrayList.size() ;
end = arrayList.size() + 2 ;
requestWithSomeHttpHeaders2(start,end);
new Handler().postDelayed(new Runnable() { // This thread runs in the UI
#Override
public void run() {
loading = true;
}
},2000);
}
}
}
}
});
requestWithSomeHttpHeaders2(start, end);
return view ;
}
public void requestWithSomeHttpHeaders2(int s , int e) {
RequestQueue queue = Volley.newRequestQueue(getActivity());
url = "my url";
StringRequest postRequest = new StringRequest(Request.Method.GET, url ,
new Response.Listener<String> ()
{
#Override
public void onResponse(String response) {
try {
progressBar.setVisibility(View.GONE);
JSONObject jsonObject = new JSONObject(response);
JSONArray payload = jsonObject.getJSONArray("Payload");
JSONObject MetaData = jsonObject.getJSONObject("MetaData");
System.out.println(response);
totalcount = MetaData.getInt("TotalCount");
System.out.println("200" + " " + totalcount);
System.out.println("payload length"+payload.length());
int i ;
for(i =0 ; i < payload.length() ; i++)
{
System.out.println(payload.getJSONObject(i).getString("image_title"));
System.out.println(payload.getJSONObject(i).getString("image_title"));
System.out.println(payload.getJSONObject(i).getString("image_file"));
System.out.println(payload.getJSONObject(i).getString("image_description"));
System.out.println(payload.getJSONObject(i).getString("image_category"));
System.out.println(payload.getJSONObject(i).getString("image_tags"));
System.out.println(payload.getJSONObject(i).getString("id"));
System.out.println(payload.getJSONObject(i).getString("favourite"));
String newString = payload.getJSONObject(i).getString("image_file").replace("original_image", "thumbnail");
CardSetterGetter all = new CardSetterGetter(payload.getJSONObject(i).getString("image_file"),
payload.getJSONObject(i).getString("image_title"),
payload.getJSONObject(i).getString("image_description"),
payload.getJSONObject(i).getString("image_category"),
payload.getJSONObject(i).getString("image_tags"),
payload.getJSONObject(i).getString("id"),
payload.getJSONObject(i).getString("favourite"));
System.out.println("i value is " + i);
arrayList.add(all);
Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
adapter = new RecyclerViewAdapter(getActivity(),arrayList,imageNameArray,totalItemCount);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
//adapter.notifyItemInserted(arrayList.size() - 1);
if (end >= totalcount)
{
int index = totalcount -1 ;
recyclerView.scrollToPosition(index);
}
else {
recyclerView.scrollToPosition(end);
}
}
};
handler.post(r);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("error" + e);
}
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.d("ERROR","error => "+error.toString());
// definitions.setText("check your internet connection");
NetworkResponse networkResponse = error.networkResponse;
// Log.e("Volley", "Error. HTTP Status Code:"+networkResponse.statusCode);
if (networkResponse != null) {
Log.e("Volley", "Error. HTTP Status Code:"+networkResponse.statusCode);
}
if (error instanceof TimeoutError) {
Log.e("Volley", "TimeoutError");
}else if(error instanceof NoConnectionError){
Log.e("Volley", "NoConnectionError");
} else if (error instanceof AuthFailureError) {
Log.e("Volley", "AuthFailureError");
} else if (error instanceof ServerError) {
Log.e("Volley", "ServerError");
} else if (error instanceof NetworkError) {
Log.e("Volley", "NetworkError");
} else if (error instanceof ParseError) {
Log.e("Volley", "ParseError");
}
}
}
);
queue.add(postRequest);
}
public void getdata(){
try {
SharedPreferences sharedPref = getActivity().getSharedPreferences("mobileId" , Context.MODE_PRIVATE);
androidId = sharedPref.getString("mobileId" , "");
sharedPref = getActivity().getSharedPreferences("categoryInfo" , Context.MODE_PRIVATE);
categoryName = sharedPref.getString("categoryName" , "");
cateGoryFlag = sharedPref.getString("categoryFlag" , "");
tagname = sharedPref.getString("tagname" , "");
}catch (Exception e){
}
}
}
I tried removing if else part of the code, but that made the recyclerView scroll to the top whenever user reach the bottom of the recyclerView.
Please tell me if you need more of the code or code of RecyclerViewAdapter.
I fixed a similar problem by providing the correct orientation to the layout manager. I would change your code to something like:
public RecyclerView.Adapter adapter ;
adapter = new RecyclerViewAdapter(getActivity(),arrayList,imageNameArray,totalItemCount);
recyclerView.setHasFixedSize(true);
//This line should do the trick:
//first parameter is the context
//second parameter is the orientation
//third parameter is used for reverse layout (if you need to show items from last to first)
layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
//probably better to use notifyDataSetChanged to let the adapter know you just initialized it (instead of notifying a single element)
adapter.notifyDataSetChanged();
Not sure why you provide the total item count to the adapter as well, but that's outside the scope of the question and surely doesn't give any problems.
EDIT:
Now that you posted the whole fragment code, I am seeing at least a couple problems:
- the RecyclerView initialization should not be in a runnable, but in the onCreateView or some starting function. You just need to set the manager and the adapter once.
- You provide imageNameArray to your adapter, but where are you inserting new items into it? If you want your RecyclerView to scroll down to the last inserted item, you first need to add an item to the ArrayList, then notify the insertion at that position, something like this:
int position = imageNameAray.size();
imageNameArray.add(item);
adapter.notifyItemInserted(position); //this makes the view update the item in that position, making the recycler to scroll there

How can I smoothly load the data from the adapter and set into the fragment listview in android?

Explanation:
I have implement a navigationDrawer. In which myFirstFragment it means in my homeFragment,I have viewpager and listview.I have set my data and data loaded completely in both.
When I click on one of the row of the listview,it calls a class name GetValue and inside the GetValue.I passed an intent to open an activity namely ScoreCard.
In Scorecard,I have implemented a tablayout with viewpager so I have multiple fragments inside my ScoreCard.Fragment like ONE,TWO,THREE etc.
My All the fragment which load the data from the server.
Everything working correctly but the problem is when I click on the row of the listview which was set into my home_fragment it loaded scorecard and scorecard loaded the fragment.
During the load of the fragment,I press back button of my device and application was unfortunately crashed.
Here is post some code which work after pressing the row of the listview which reside on homeFragment.
Here is my homeFragment in which I call and adapter and set the value to the listview.
ScheduleAdapter CmAdapter = new ScheduleAdapter(getContext(), arr_completed, lst_key2);
CmAdapter.notifyDataSetChanged();
completed_listview.setAdapter(CmAdapter);
Here is ScheduleAdapter.java
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
match_key = arr_matchKey.get(position);
Log.e("Schedule complted key", match_key);
MainActivity activity = (MainActivity) context;
GetValue gv = new GetValue(context);
gv.setFullUrl(match_key);
gv.setAccessToken(activity.getMyData());
gv.execute();
}
});
Here is my GetValue.java class which get the data from server and called ScoreCard activity
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(st_overview.equals("abandoned") || st_overview.equals("canceled"))
{
DialogAbandoned ad=new DialogAbandoned(context);
ad.setDialog(short_name,msg_info+".");
}
else {
Intent intent = new Intent(context, ScoreCard.class);
intent.putExtra("tabvalue", tabVlaue);
intent.putExtra("teamName", name_of_team);
intent.putExtra("tabData", tabData);
intent.putExtra("match_key", match_key);
intent.putExtra("access_token", accessToken);
intent.putExtra("team_names", teams_name);
intent.putExtra("inn_len", inn_len);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
Here is my ScoreCard.java activity which have tablayout with viewpager
public class ScoreCard extends AppCompatActivity {
Toolbar toolbar;
public ViewPager viewPager;
public TabLayout tabLayout;
String[] team_name = new String[10];
String[] runs = new String[4];
String[] wicket = new String[4];
String[] name_of_team_split;
public String[] parts, parts1;
public String name_of_team = "";
public String tab_value = "";
public String match_key = "";
public String tabData = "";
public int tabSelector;
public String access_token = "";
public String header_team_name = "";
int inn_len = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_score_card);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
Intent i = getIntent();
tab_value = i.getStringExtra("tabvalue");
tabData = i.getStringExtra("tabData");
name_of_team = i.getStringExtra("teamName");
inn_len = i.getIntExtra("inn_len", 0);
match_key = i.getStringExtra("match_key");
access_token = i.getStringExtra("access_token");
header_team_name = i.getStringExtra("team_names");
if (header_team_name != null && header_team_name != "") {
getSupportActionBar().setTitle(header_team_name);
}
try {
parts1 = tabData.split("`");
int k = 0;
for (int a = 0; a < parts1.length; a++, k++) {
try {
JSONObject obj = new JSONObject(parts1[a]);
runs[k] = obj.getString("runs");
wicket[k] = obj.getString("wickets");
} catch (JSONException e) {
e.printStackTrace();
}
}
name_of_team_split = name_of_team.split("=");
for (int b = 0; b < name_of_team_split.length; b++) {
JSONObject team1 = new JSONObject(name_of_team_split[b]);
team_name[b] = team1.getString("short_name");
}
} catch (JSONException e) {
e.printStackTrace();
}
setTabValue(tab_value);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
if (tabSelector == 1) {
viewPager.setCurrentItem(0, false);
} else if (tabSelector == 2) {
viewPager.setCurrentItem(1, false);
} else if (tabSelector == 3) {
viewPager.setCurrentItem(2, false);
} else if (tabSelector == 4) {
viewPager.setCurrentItem(4, false);
}
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
private void setupTabIcons() {
if (tabSelector == 1) {
tabLayout.getTabAt(0).setText(team_name[0] + "-" + runs[0] + "/" + wicket[0]);
} else if (tabSelector == 2) {
tabLayout.getTabAt(0).setText(team_name[0] + "-" + runs[0] + "/" + wicket[0]);
tabLayout.getTabAt(1).setText(team_name[1] + "-" + runs[1] + "/" + wicket[1]);
} else if (tabSelector == 3) {
tabLayout.getTabAt(0).setText(team_name[0] + "-" + runs[0] + "/" + wicket[0]);
tabLayout.getTabAt(1).setText(team_name[1] + "-" + runs[1] + "/" + wicket[1]);
tabLayout.getTabAt(2).setText(team_name[2] + "-" + runs[2] + "/" + wicket[2]);
} else if (tabSelector == 4) {
tabLayout.getTabAt(0).setText(team_name[0] + "\n" + runs[0] + "/" + wicket[0]);
tabLayout.getTabAt(1).setText(team_name[1] + "\n" + runs[1] + "/" + wicket[1]);
tabLayout.getTabAt(2).setText(team_name[2] + "\n" + runs[2] + "/" + wicket[2]);
tabLayout.getTabAt(3).setText(team_name[3] + "\n" + runs[3] + "/" + wicket[3]);
}
}
public void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
if (tabSelector == 1) {
adapter.addFragment(new OneFragment());
} else if (tabSelector == 2) {
adapter.addFragment(new OneFragment());
adapter.addFragment(new TwoFragment());
} else if (tabSelector == 3) {
adapter.addFragment(new OneFragment());
adapter.addFragment(new TwoFragment());
adapter.addFragment(new ThreeFragment());
} else if (tabSelector == 4) {
adapter.addFragment(new OneFragment());
adapter.addFragment(new TwoFragment());
adapter.addFragment(new ThreeFragment());
adapter.addFragment(new FourFragment());
}
viewPager.setAdapter(adapter);
}
public void setTabValue(String tabs) {
parts = tabs.split(",");
int len = parts.length;
if (len == 1) {
tabSelector = 1;
} else if (len == 2) {
tabSelector = 2;
} else if (len == 3) {
tabSelector = 3;
} else if (len == 4) {
tabSelector = 4;
}
}
public String setInningScore() {
return tab_value;
}
public String geturl() {
return match_key;
}
public String GetAccessToken() {
return access_token;
}
public int setInningLength() {
return inn_len;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if(menu!=null){
menu.findItem(R.id.Score).setVisible(false);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
}
Here is my OneFragent which calls from scorecard. I only post the code which required according to my question
adapter = new FullScoreAdapter(getContext(), p_name, p_key);
adapter.notifyDataSetChanged();
lst.setAdapter(adapter);
Helper.getListViewSize(lst);
above adapter calls the FullScoreAdapter and set the data into listview of the OneFragment
Here is my FullScoreAdapter
public class FullScoreAdapter extends BaseAdapter {
private Context context;
private List<String> batting_order;
private List<JSONObject> player_key;
int size=0;
String batting_ord="";
public static LayoutInflater inflater=null;
public FullScoreAdapter(Context context,List<String> batting_order,List<JSONObject> player_key){
this.context=context;
this.batting_order=batting_order;
if (batting_order != null && !batting_order.isEmpty()) {
size = batting_order.size();
}
this.player_key=player_key;
}
#Override
public int getCount() {
return this.batting_order.size();
}
#Override
public Object getItem(int position) {
return batting_order.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public class Holder {
TextView txtname;
TextView txtballs;
TextView txtRuns;
TextView txtsixs;
TextView txtfours;
TextView txtout;
ImageView strike_ball;
LinearLayout out_layout_hide;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder= new Holder();
Typeface tf;
String fullname="",Balls="",Runs="",sixes="",fours="";
if(convertView==null) {
inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);//Here i got an error like java.lang.nullpointerException
convertView = inflater.inflate(R.layout.list_rows, null);
tf=Typeface.createFromAsset(convertView.getResources().getAssets(), "Roboto-Regular.ttf");
holder.txtname = (TextView) convertView.findViewById(R.id.txtName);
holder.txtname.setTypeface(tf,Typeface.BOLD);
holder.txtballs = (TextView) convertView.findViewById(R.id.txtBalls);
holder.txtballs.setTypeface(tf);
holder.txtRuns=(TextView)convertView.findViewById(R.id.txtRuns);
holder.txtRuns.setTypeface(tf);
holder.txtsixs=(TextView)convertView.findViewById(R.id.txtSixs);
holder.txtsixs.setTypeface(tf);
holder.txtfours=(TextView)convertView.findViewById(R.id.txtFours);
holder.txtfours.setTypeface(tf);
holder.txtout=(TextView)convertView.findViewById(R.id.out);
holder.txtout.setTypeface(tf);
holder.strike_ball=(ImageView)convertView.findViewById(R.id.strike_ball);
holder.out_layout_hide=(LinearLayout)convertView.findViewById(R.id.out_layout_color);
convertView.setTag(holder);
try {
JSONObject obj = this.player_key.get(position);
batting_ord=this.batting_order.get(position);
fullname=obj.getString("fullname");
JSONObject match=obj.getJSONObject("match");
JSONObject bats_innings=match.getJSONObject("innings");
JSONObject first_inning=bats_innings.getJSONObject("1");
JSONObject first_batting=first_inning.getJSONObject("batting");
if(first_batting.isNull("balls")) {
if(first_batting.isNull("runs")){
Runs="0";
}
else{
Runs=first_batting.getString("runs");
}
Balls="0";
sixes="0";
fours="0";
}
else{
Balls=first_batting.getString("balls");
Runs=first_batting.getString("runs");
sixes=first_batting.getString("sixes");
fours=first_batting.getString("fours");
}
try{
if(first_batting.has("out_str")){
String out=first_batting.getString("out_str");
holder.txtout.setText(out);
holder.strike_ball.setVisibility(View.GONE);
}
else{
holder.strike_ball.setVisibility(View.VISIBLE);
holder.txtout.setText("not out");
}
}
catch (JSONException e)
{
e.printStackTrace();
}
holder.txtname.setText(fullname);
holder.txtRuns.setText(Runs);
holder.txtballs.setText(Balls);
holder.txtfours.setText(fours);
holder.txtsixs.setText(sixes);
}
catch (JSONException e){
e.printStackTrace();
}
int setcolor=position;
if(setcolor%2==0){
convertView.setBackgroundColor(Color.parseColor("#FFFFFF"));
holder.out_layout_hide.setBackgroundColor(Color.parseColor("#EFF5F5"));
}
else{
convertView.setBackgroundColor(Color.parseColor("#FFFFFF"));
holder.out_layout_hide.setBackgroundColor(Color.parseColor("#EFF5F5"));
}
}
else {
holder = (Holder) convertView.getTag();
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent player_intent=new Intent(context, PlayerIccStats.class);
player_intent.putExtra("player_key",batting_order.get(position));
context.startActivity(player_intent);
}
});
return convertView;
}
}
Error i got when my tabs are loaded at the time i pressed a back button.
FATAL EXCEPTION: main
java.lang.NullPointerException
at adapter.FullScoreAdapter.getView(FullScoreAdapter.java:78)
at comman.Helper.getListViewSize(Helper.java:20)
at fragments.OneFragment$JSONLoader.onPostExecute(OneFragment.java:593)
at fragments.OneFragment$JSONLoader.onPostExecute(OneFragment.java:300)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4950)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
at dalvik.system.NativeStart.main(Native Method)
Please Help me to solve out this problem.

Categories

Resources