7

I have implemented one app where I am using RecyclerView in fragments. There are 3 buttons, 1 image and some text on every item. If I scroll and click on "View Profile" button then new activity will open which is running successfully but when I call back button then the Item is coming on start position. I need item will come at the same position.

Item Image

Code for Fragment

public class Broader_Match_Tab extends Fragment{

int lastVisibleItemPosition;
SessionManager session;
private List<SuperHero> listSuperHeroes;
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
public ProgressBar progressBar;
private RequestQueue requestQueue;
private int requestCount1 = 1;
private Boolean isStarted = false;
private Boolean isVisible = false;

boolean isLastPageLoaded = false;

public String email;
TextView tvMSG;
public Broader_Match_Tab() {}

@Override
public void onStart() {
    super.onStart();
    isStarted = true;
    if (isVisible && isStarted){
        getData();
    }
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    isVisible = isVisibleToUser;
    if (isStarted && isVisible && (! isLastPageLoaded)) { getData(); } }

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view= inflater.inflate(R.layout.activity_main_test, container, false);

    session = new SessionManager(getActivity());
    // get user data from session
    HashMap<String, String> user = session.getUserDetails();
    email = user.get(SessionManager.KEY_EMAIL);
    return view;
}

public void onViewCreated(View v, Bundle savedInstanceState) {
    super.onViewCreated(v, savedInstanceState);
    recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    layoutManager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(layoutManager);
    listSuperHeroes = new ArrayList<>();
    requestQueue = Volley.newRequestQueue(getContext());
    adapter = new CardAdapter(listSuperHeroes, getActivity());
    recyclerView.setAdapter(adapter);
    progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
    tvMSG = (TextView)v.findViewById(R.id.tvMSG);

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int
                newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (isLastItemDisplaying(recyclerView)) {
                    getData();
            }
        }
    });
}

private JsonArrayRequest getDataFromServer(int requestCount) {
    final String DATA_URL = "https://www.example.com";
    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL + String.valueOf(requestCount),
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    if (response.length() == 0) {
                        progressBar.setVisibility(View.GONE);
                        tvMSG.setText("There is no broader matches");
                        isLastPageLoaded = true;
                    }
                    else {
                        parseData(response);
                        tvMSG.setVisibility(View.GONE);
                        progressBar.setVisibility(View.GONE);
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    progressBar.setVisibility(View.GONE);
                    Toast.makeText(getActivity(), "No More Items Available", Toast.LENGTH_SHORT).show();
                }
            });
    return jsonArrayRequest;
}

private void getData() {
    if(!isLastPageLoaded){
        requestQueue.add(getDataFromServer(requestCount1));
        requestCount1++;
    }}

private void parseData(JSONArray array) {
    for (int i = 0; i < array.length(); i++) {
        SuperHero superHero = new SuperHero();
        JSONObject json = null;
        try {
            json = array.getJSONObject(i);
            superHero.setImageUrl(json.getString(Config_Test.TAG_IMAGE_URL));
            superHero.setMglId(json.getString(Config_Test.TAG_MGLID));
            superHero.setAge(json.getString(Config_Test.TAG_AGE));
            superHero.setAgeHeight(json.getString(Config_Test.TAG_AGEHEIGHT));
            superHero.setCommunity(json.getString(Config_Test.TAG_COMMUNITY));
            superHero.setCaste(json.getString(Config_Test.TAG_CASTE));
            superHero.setOccupation(json.getString(Config_Test.TAG_OCCUPATION));
            superHero.setIncome(json.getString(Config_Test.TAG_INCOME));
            superHero.setShortlist(json.getString(Config_Test.TAG_SHORTLIST));
            superHero.setExpress_Intrest(json.getString(Config_Test.TAG_EXPRESSINTREST));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        listSuperHeroes.add(superHero);
    }
    adapter.notifyDataSetChanged();
}
private boolean isLastItemDisplaying(RecyclerView recyclerView) {
    if (recyclerView.getAdapter().getItemCount() != 0) {
        lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
        if (lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1)
            return true;
    }
    return false;
  }
}

Adapter Code

public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder>
{
private static final String url ="https://www.example.com";
private static final String url1 = "https://www.example.com";
private static final String KEY_MATRI_ID_TO="matriID_to";
private static final String KEY_MATRI_ID_BY="matriID_by";

SessionManager session;
public String matri_id_to, matri_id_by, str_gender;
String str_shortlist,str_EI;

//Imageloader to load image
private ImageLoader imageLoader;
private Context context;

//List to store all superheroes
List<SuperHero> superHeroes;

//Constructor of this class
public CardAdapter(List<SuperHero> superHeroes, Context context){
    super();
    //Getting all superheroes
    this.superHeroes = superHeroes;
    this.context = context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.superheroes_list, parent, false);
    // Session class instance
    session = new SessionManager(context);
    session.checkLogin();
    // get user data from session
    HashMap<String, String> user = session.getUserDetails();
    matri_id_by = user.get(SessionManager.KEY_EMAIL);
    str_gender = user.get(SessionManager.KEY_GENDER);

    ViewHolder viewHolder = new ViewHolder(v);
    return viewHolder;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {

    //Getting the particular item from the list
    final SuperHero superHero =  superHeroes.get(position);

    //Loading image from url
    imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
    if(str_gender.equalsIgnoreCase("Male")) {
        imageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView, R.drawable.image, R.drawable.girl));
    }
    else {
        imageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView, R.drawable.image, R.drawable.boy));
    }

    int pos = getItemViewType(position);
    if(superHeroes.get(pos).getImageUrl() == null) {
        holder.imageView.setVisibility(View.GONE);
    } else {
        holder.imageView.setImageUrl(superHero.getImageUrl(), imageLoader);
    }

    holder.textViewId.setText(superHero.getMglId());
    holder.AgeHeight.setText(superHero.getAgeHeight()+" / "+superHero.getAge());
    holder.Community.setText(superHero.getCommunity()+" / "+superHero.getCaste());
    holder.Occupation.setText(superHero.getOccupation());
    holder.Income.setText(superHero.getIncome());

    str_shortlist = superHero.getShortlist();
    if(str_shortlist.toString().equalsIgnoreCase("Shortlisted")) {
        holder.btnShortlist.setText(str_shortlist);
        holder.btnShortlist.setBackgroundColor(Color.parseColor("#FF0E3671"));
        holder.btnShortlist.setEnabled(false);
    }
    else{
        holder.btnShortlist.setEnabled(true);
        holder.btnShortlist.setText(str_shortlist);
        holder.btnShortlist.setBackgroundColor(Color.parseColor("#2a7fff"));
    }


    str_EI = superHero.getExpress_Intrest();
    Log.e("str_EI_____",str_EI);
    if(str_EI.toString().equalsIgnoreCase("Accepted")) {
        holder.btnEI.setText(str_EI);
        holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
        holder.btnEI.setEnabled(false);
    }
    else if(str_EI.toString().equalsIgnoreCase("Reject")){
        holder.btnEI.setText(str_EI);
        holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
        holder.btnEI.setEnabled(false);
    }
    else if(str_EI.toString().equalsIgnoreCase("Declined")){
        holder.btnEI.setText(str_EI);
        holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
        holder.btnEI.setEnabled(false);
    }
    else if(str_EI.toString().equalsIgnoreCase("Pending..")){
        holder.btnEI.setText(str_EI);
        holder.btnEI.setBackgroundColor(Color.parseColor("#FF045B49"));
        holder.btnEI.setEnabled(false);
    }
    else
    {
        holder.btnEI.setEnabled(true);
        holder.btnEI.setText(str_EI);
        holder.btnEI.setBackgroundColor(Color.parseColor("#00aa88"));
    }


    holder.btnShortlist.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            superHero.setShortlist("Wait...");
            holder.btnShortlist.setText(superHero.getShortlist());
            matri_id_to = superHero.getMglId();
            holder.shortlist(position);
        }
    });

    holder.btnViewProfile.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent n = new Intent(holder.itemView.getContext(),BlankActivity.class);
            String str_id = holder.textViewId.getText().toString();
            n.putExtra("ID",str_id);
            holder.itemView.getContext().startActivity(n);
        }
    });


    holder.btnEI.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            superHero.setExpress_Intrest("Wait...");
            holder.btnEI.setText(superHero.getExpress_Intrest());
            matri_id_to = superHero.getMglId();
            holder.expressInterest(position);
        }
    });

}

public SuperHero getItem(int position){
    return superHeroes.get(position);
}

@Override
public int getItemCount() {return superHeroes.size();}

    @Override
    public int getItemViewType(int position) {
        return position;
    }

class ViewHolder extends RecyclerView.ViewHolder{
    public NetworkImageView imageView;
    public TextView textViewId;
    public TextView AgeHeight;
    public TextView Community;
    public TextView Occupation;
    public TextView Income;

    public Button btnShortlist;
    public Button btnViewProfile;
    public Button btnEI;

    //Initializing Views
    public ViewHolder(final View itemView) {
        super(itemView);
        imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewHero);
        textViewId = (TextView) itemView.findViewById(R.id.textViewId);
        AgeHeight = (TextView) itemView.findViewById(R.id.AgeHeight);
        Community = (TextView) itemView.findViewById(R.id.Community);
        Occupation = (TextView) itemView.findViewById(R.id.Occupation);
        Income = (TextView) itemView.findViewById(R.id.Income);
        btnShortlist = (Button) itemView.findViewById(R.id.btnshort);
        btnViewProfile = (Button) itemView.findViewById(R.id.buttonViewProfile);
        btnEI = (Button) itemView.findViewById(R.id.btnExpressIntrest);
    }

    public void shortlist(final int position) {
        StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                if (response.trim().equalsIgnoreCase("success")) {
                    superHeroes.get(position).setShortlist("Shortlisted");
                    // holder.btnShortlist.setText(superHero.getShortlist());
                    notifyDataSetChanged();
                }
            }
        },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(context, error.toString(), Toast.LENGTH_LONG).show();
                    }
                }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put(KEY_MATRI_ID_BY, matri_id_by);
                params.put(KEY_MATRI_ID_TO, matri_id_to);
                return params;
            }
        };
        RequestQueue requestQueue = Volley.newRequestQueue(context);
        requestQueue.add(stringRequest);
    }

    public void expressInterest(final int position) {
        StringRequest stringRequest1 = new StringRequest(Request.Method.POST, url1, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                if(response.trim().equalsIgnoreCase("success")) {
                    superHeroes.get(position).setExpress_Intrest("Pending..");
                    notifyDataSetChanged();
                }
            }
        },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(context, error.toString(), Toast.LENGTH_LONG).show();
                    }
                }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put(KEY_MATRI_ID_BY,matri_id_by);
                params.put(KEY_MATRI_ID_TO,matri_id_to);
                return params;
            }
        };
        RequestQueue requestQueue = Volley.newRequestQueue(context);
        requestQueue.add(stringRequest1);
    }
   }
  }
Paramjeet Singh
  • 145
  • 1
  • 3
  • 15

7 Answers7

4

Save Instance Code:

Parcelable mListState;

protected void onSaveInstanceState(Bundle state) {
     super.onSaveInstanceState(state);

     // Save list state
     mListState = mLayoutManager.onSaveInstanceState();
     state.putParcelable(LIST_STATE_KEY, mListState);
}

Restore State Code:

protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);

    // Retrieve list state and list/item positions
    if(state != null)
        mListState = state.getParcelable(LIST_STATE_KEY);
}

Here in onResume() update the layout manager:

@Override
protected void onResume() {
    super.onResume();

    if (mListState != null) {
        mLayoutManager.onRestoreInstanceState(mListState);
    }
}

Hope this helps

Rahul Singh Chandrabhan
  • 2,531
  • 5
  • 22
  • 33
2

The main problem is that onPause you are clearing the whole data and when the fragment getting visible again you are requesting to server from the page 1. Comment the following code.

    @Override
public void onPause(){
    super.onPause();
    //listSuperHeroes.clear();
    //adapter.notifyDataSetChanged();
    //requestCount1=1;
   }
  }

update the isLastPageLoaded here:

private boolean isLastPageUpdated = false;
     private JsonArrayRequest getDataFromServer(int requestCount) {
            final String DATA_URL = "https://www.XYZ.php?matri_id="+email+"&page=";
            JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL + String.valueOf(requestCount),
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray response) {
                            if (response.length() == 0) {
                                progressBar.setVisibility(View.GONE);
                                tvMSG.setText("There is no broader matches");
                    isLastPageLoaded = true;
                            }
                            else {
                                parseData(response);
                                tvMSG.setVisibility(View.GONE);
                                progressBar.setVisibility(View.GONE);
                            }
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            progressBar.setVisibility(View.GONE);
                            Toast.makeText(getActivity(), "No More Items 
                            Available", Toast.LENGTH_SHORT).show();
                        }
                    });
            return jsonArrayRequest;
        }

and in getData()

 private void getData() {
if(!isLastPageUpdated){
    requestQueue.add(getDataFromServer(requestCount1));
    requestCount1++;
}}
Paramjeet Singh
  • 145
  • 1
  • 3
  • 15
Arvind
  • 444
  • 4
  • 14
  • so when you are launching new activity onPause method of fragment getting called and all adapter data is getting cleared. When you pressed back button from the current activity, onresume() method getting called along with setUserVisiblityHint() method. onPause method setting the requestcount value to 1, so you are able to load data only for the first page. suppose you clicked the item which is on 5th page so coming back to fragment you have only first page data. how are you supposing that recycler view should scroll to 5th page when it has only first page data?? – Arvind Jan 24 '18 at 10:18
  • When I have scrolled all the item and changed the tab and come back on previous tab then it shows "No more item available" – Paramjeet Singh Jan 24 '18 at 10:27
  • yes, because if you are moving to the adjacent tab of the current fragment then the current fragment is in memory and it is not getting loaded again if you are moving to the previous fragment. and in the fragment, you have moved to the last page. – Arvind Jan 24 '18 at 10:32
  • make a flag value to track the pageCount. If you already reached to the max number of the page then don't call the getData method in the setUserVisiblityHint method. – Arvind Jan 24 '18 at 10:35
  • Take a boolean isLastPageLoaded = false; when you reached to the last page make isLastPageLoaded = true; In @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); isVisible = isVisibleToUser; if (isStarted && isVisible && (! isLastPageLoaded)) { getData(); } } – Arvind Jan 24 '18 at 10:52
  • for more visibility check the condition in getDataMethod like : private void getData() { if(!isLastPageLoaded){ requestQueue.add(getDataFromServer(requestCount1)); requestCount1++; }} – Arvind Jan 24 '18 at 11:14
  • what is the server response if I pass an invalid page number or exceeded page count than actual?? – Arvind Jan 24 '18 at 12:19
  • when json is empty you are setting text tvMSG.setText("There is no broader matches"); Put some logs and you will get the answer. – Arvind Jan 24 '18 at 12:48
0

save the position of adapter in some variable in adapter. change scroll to that position on back pressed using

linearLayoutManager.scrollToPositionWithOffset(int, int);

inside activity.

jitendra purohit
  • 652
  • 5
  • 18
0

You need to override onBackPressed() and add recyclerView.scrollToPosition(position);

@Override
public void onBackPressed() {
    super.onBackPressed();
    recyclerView.scrollToPosition(position);
    finish();
}
0

save the position of item clicked in onSaveInstanceState and pass that to scrollToPosition or

try below

private static final String SELECTED_KEY = "selected_position";

@Override
    public void onSaveInstanceState(Bundle outState) {
        lastFirstVisiblePosition = ((LinearLayoutManager)mRecylerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
        outState.putInt(SELECTED_KEY, lastFirstVisiblePosition);
    }

in Oncreate

Edited..

if(savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY))
        {
            lastFirstVisiblePosition = savedInstanceState.getInt(SELECTED_KEY);


        }

use ((LinearLayoutManager) mRecylerView.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition) or

mRecylerView.smoothScrollToPosition(lastFirstVisiblePosition); after data is populated, preferably after adapter.notifyDataSetChanged();

tanni tanna
  • 544
  • 4
  • 12
  • use int lastFirstVisiblePosition=-1; to start with it is the first view ( recyclerview item) at the top . – tanni tanna Jan 24 '18 at 10:01
  • Please see updated answer, important thing is using below line after data is populated, mRecylerView.smoothScrollToPosition(mPosition); – tanni tanna Jan 24 '18 at 10:18
0

I was experiencing the same issue before, then I solved my problem with a simpler solution. I just called adapter.startListening(); in onViewCreated() instead of onStart and called adapter.stopListening(); in onDestroyView() instead of onStop(). That prevented the entire list from regenerating while coming back from next activity and thus retained the scroll position where it was previously.

iminiki
  • 2,549
  • 12
  • 35
  • 45
Margembul
  • 1
  • 1
0

I've solved the problem as follow:

Called .startListening in both onViewCreated and in onStart

Called .stopListening in onDestroyView

Don't call .stopListening in onStop

My code in the fragment as follow:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle 
savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (mAdapterHb != null) {
        mAdapterHb.startListening();
    }
}
@Override
public void onStart() {
    super.onStart();
    if (mAdapterHb != null) {
        mAdapterHb.startListening();
    }
}

@Override
public void onStop() {
    super.onStop();
//        if (mAdapterHb != null) {
//            mAdapterHb.stopListening();
//        }
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    if (mAdapterHb != null) {
        mAdapterHb.stopListening();
    }
}
Leo S
  • 159
  • 9