Cannot Maintain Firestore RecyclerView State On Back Navigation












0















I have a Fragment that contains a Recylcerview. This RecyclerView is populated using the Firebase FirestoreUI.



Below is the code for my RecyclerView, which I call in .onStart() to listen to changes:



@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
mRecyclerViewState = savedInstanceState.getParcelable(RECYCLERVIEW_STATE);
}
mRecyclerview = (RecyclerView) view.findViewById(R.id.list);
mPollHolderArray = new ArrayList<>();
mRecyclerview.getItemAnimator().setChangeDuration(0);


mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//TODO: Detertmine if necessary since ordering is now different in Firebase
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
startActivity(I);
}
});


mRecyclerview.setLayoutManager(mLayoutManager);

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


if (mFirestoreAdaper == null) {
Query queryStore = FirebaseFirestore.getInstance()
.collection(POLLS_LABEL)
.orderBy("timestamp", Query.Direction.ASCENDING);
//Cloud Firestore does not have any ordering; must implement a timestampe to order sequentially

FirestoreRecyclerOptions<Poll> storeOptions = new FirestoreRecyclerOptions.Builder<Poll>()
.setQuery(queryStore, Poll.class)
.build();
mFirestoreAdaper = new FirestoreRecyclerAdapter<Poll, PollHolder>(storeOptions) {
@Override
protected void onBindViewHolder(@NonNull final PollHolder holder, final int position, @NonNull Poll model) {
holder.mPollQuestion.setText(model.getQuestion());
String voteCount = String.valueOf(model.getVote_count());
//TODO: Investigate formatting of vote count for thousands
holder.mVoteCount.setText(voteCount);
Picasso.get()
.load(model.getImage_URL())
.fit()
.into(holder.mPollImage);
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent toClickedPoll = new Intent(getActivity(), PollHostActivity.class);
String recyclerPosition = getSnapshots().getSnapshot(position).getId();
Log.v("Firestore ID", recyclerPosition);
toClickedPoll.putExtra("POLL_ID", recyclerPosition);
startActivity(toClickedPoll);

}
});
}


@Override
public PollHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
return new PollHolder(v);
}


};
mRecyclerview.setAdapter(mFirestoreAdaper);
}
}


When I navigate to another Fragment (onClick of the RecyclerView) and then back to the Fragment containing this RecyclerView, I expect to be able to maintain the position that was clicked. However, this is not occurring. Below is the code I have tried to save the state, it is simply reverting back to the top item of the RecyclerView:



    @Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mRecyclerViewState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLERVIEW_STATE, mRecyclerViewState);

}


EDIT: The original Fragment is part of a ViewPager (I am testing it right now on the NewFragment):



    public class SectionPagerAdapter extends FragmentPagerAdapter {

public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TrendingFragment();
case 1:
return new FollowingFragment();
case 2:
return new NewFragment();
default:
return new TrendingFragment();
}
}









share|improve this question

























  • show the fragment transition code

    – Har Kal
    Nov 22 '18 at 2:57











  • it might happen you are loading a fresh fragment on every click

    – Har Kal
    Nov 22 '18 at 2:58











  • What exact code do you need to see? Thanks for the help

    – tccpg288
    Nov 22 '18 at 2:59











  • the code you use to transit from one fragment to another

    – Har Kal
    Nov 22 '18 at 2:59











  • It is in the holder, there is a click Listener

    – tccpg288
    Nov 22 '18 at 3:00
















0















I have a Fragment that contains a Recylcerview. This RecyclerView is populated using the Firebase FirestoreUI.



Below is the code for my RecyclerView, which I call in .onStart() to listen to changes:



@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
mRecyclerViewState = savedInstanceState.getParcelable(RECYCLERVIEW_STATE);
}
mRecyclerview = (RecyclerView) view.findViewById(R.id.list);
mPollHolderArray = new ArrayList<>();
mRecyclerview.getItemAnimator().setChangeDuration(0);


mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//TODO: Detertmine if necessary since ordering is now different in Firebase
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
startActivity(I);
}
});


mRecyclerview.setLayoutManager(mLayoutManager);

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


if (mFirestoreAdaper == null) {
Query queryStore = FirebaseFirestore.getInstance()
.collection(POLLS_LABEL)
.orderBy("timestamp", Query.Direction.ASCENDING);
//Cloud Firestore does not have any ordering; must implement a timestampe to order sequentially

FirestoreRecyclerOptions<Poll> storeOptions = new FirestoreRecyclerOptions.Builder<Poll>()
.setQuery(queryStore, Poll.class)
.build();
mFirestoreAdaper = new FirestoreRecyclerAdapter<Poll, PollHolder>(storeOptions) {
@Override
protected void onBindViewHolder(@NonNull final PollHolder holder, final int position, @NonNull Poll model) {
holder.mPollQuestion.setText(model.getQuestion());
String voteCount = String.valueOf(model.getVote_count());
//TODO: Investigate formatting of vote count for thousands
holder.mVoteCount.setText(voteCount);
Picasso.get()
.load(model.getImage_URL())
.fit()
.into(holder.mPollImage);
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent toClickedPoll = new Intent(getActivity(), PollHostActivity.class);
String recyclerPosition = getSnapshots().getSnapshot(position).getId();
Log.v("Firestore ID", recyclerPosition);
toClickedPoll.putExtra("POLL_ID", recyclerPosition);
startActivity(toClickedPoll);

}
});
}


@Override
public PollHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
return new PollHolder(v);
}


};
mRecyclerview.setAdapter(mFirestoreAdaper);
}
}


When I navigate to another Fragment (onClick of the RecyclerView) and then back to the Fragment containing this RecyclerView, I expect to be able to maintain the position that was clicked. However, this is not occurring. Below is the code I have tried to save the state, it is simply reverting back to the top item of the RecyclerView:



    @Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mRecyclerViewState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLERVIEW_STATE, mRecyclerViewState);

}


EDIT: The original Fragment is part of a ViewPager (I am testing it right now on the NewFragment):



    public class SectionPagerAdapter extends FragmentPagerAdapter {

public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TrendingFragment();
case 1:
return new FollowingFragment();
case 2:
return new NewFragment();
default:
return new TrendingFragment();
}
}









share|improve this question

























  • show the fragment transition code

    – Har Kal
    Nov 22 '18 at 2:57











  • it might happen you are loading a fresh fragment on every click

    – Har Kal
    Nov 22 '18 at 2:58











  • What exact code do you need to see? Thanks for the help

    – tccpg288
    Nov 22 '18 at 2:59











  • the code you use to transit from one fragment to another

    – Har Kal
    Nov 22 '18 at 2:59











  • It is in the holder, there is a click Listener

    – tccpg288
    Nov 22 '18 at 3:00














0












0








0








I have a Fragment that contains a Recylcerview. This RecyclerView is populated using the Firebase FirestoreUI.



Below is the code for my RecyclerView, which I call in .onStart() to listen to changes:



@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
mRecyclerViewState = savedInstanceState.getParcelable(RECYCLERVIEW_STATE);
}
mRecyclerview = (RecyclerView) view.findViewById(R.id.list);
mPollHolderArray = new ArrayList<>();
mRecyclerview.getItemAnimator().setChangeDuration(0);


mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//TODO: Detertmine if necessary since ordering is now different in Firebase
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
startActivity(I);
}
});


mRecyclerview.setLayoutManager(mLayoutManager);

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


if (mFirestoreAdaper == null) {
Query queryStore = FirebaseFirestore.getInstance()
.collection(POLLS_LABEL)
.orderBy("timestamp", Query.Direction.ASCENDING);
//Cloud Firestore does not have any ordering; must implement a timestampe to order sequentially

FirestoreRecyclerOptions<Poll> storeOptions = new FirestoreRecyclerOptions.Builder<Poll>()
.setQuery(queryStore, Poll.class)
.build();
mFirestoreAdaper = new FirestoreRecyclerAdapter<Poll, PollHolder>(storeOptions) {
@Override
protected void onBindViewHolder(@NonNull final PollHolder holder, final int position, @NonNull Poll model) {
holder.mPollQuestion.setText(model.getQuestion());
String voteCount = String.valueOf(model.getVote_count());
//TODO: Investigate formatting of vote count for thousands
holder.mVoteCount.setText(voteCount);
Picasso.get()
.load(model.getImage_URL())
.fit()
.into(holder.mPollImage);
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent toClickedPoll = new Intent(getActivity(), PollHostActivity.class);
String recyclerPosition = getSnapshots().getSnapshot(position).getId();
Log.v("Firestore ID", recyclerPosition);
toClickedPoll.putExtra("POLL_ID", recyclerPosition);
startActivity(toClickedPoll);

}
});
}


@Override
public PollHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
return new PollHolder(v);
}


};
mRecyclerview.setAdapter(mFirestoreAdaper);
}
}


When I navigate to another Fragment (onClick of the RecyclerView) and then back to the Fragment containing this RecyclerView, I expect to be able to maintain the position that was clicked. However, this is not occurring. Below is the code I have tried to save the state, it is simply reverting back to the top item of the RecyclerView:



    @Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mRecyclerViewState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLERVIEW_STATE, mRecyclerViewState);

}


EDIT: The original Fragment is part of a ViewPager (I am testing it right now on the NewFragment):



    public class SectionPagerAdapter extends FragmentPagerAdapter {

public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TrendingFragment();
case 1:
return new FollowingFragment();
case 2:
return new NewFragment();
default:
return new TrendingFragment();
}
}









share|improve this question
















I have a Fragment that contains a Recylcerview. This RecyclerView is populated using the Firebase FirestoreUI.



Below is the code for my RecyclerView, which I call in .onStart() to listen to changes:



@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
mRecyclerViewState = savedInstanceState.getParcelable(RECYCLERVIEW_STATE);
}
mRecyclerview = (RecyclerView) view.findViewById(R.id.list);
mPollHolderArray = new ArrayList<>();
mRecyclerview.getItemAnimator().setChangeDuration(0);


mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//TODO: Detertmine if necessary since ordering is now different in Firebase
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
startActivity(I);
}
});


mRecyclerview.setLayoutManager(mLayoutManager);

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


if (mFirestoreAdaper == null) {
Query queryStore = FirebaseFirestore.getInstance()
.collection(POLLS_LABEL)
.orderBy("timestamp", Query.Direction.ASCENDING);
//Cloud Firestore does not have any ordering; must implement a timestampe to order sequentially

FirestoreRecyclerOptions<Poll> storeOptions = new FirestoreRecyclerOptions.Builder<Poll>()
.setQuery(queryStore, Poll.class)
.build();
mFirestoreAdaper = new FirestoreRecyclerAdapter<Poll, PollHolder>(storeOptions) {
@Override
protected void onBindViewHolder(@NonNull final PollHolder holder, final int position, @NonNull Poll model) {
holder.mPollQuestion.setText(model.getQuestion());
String voteCount = String.valueOf(model.getVote_count());
//TODO: Investigate formatting of vote count for thousands
holder.mVoteCount.setText(voteCount);
Picasso.get()
.load(model.getImage_URL())
.fit()
.into(holder.mPollImage);
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent toClickedPoll = new Intent(getActivity(), PollHostActivity.class);
String recyclerPosition = getSnapshots().getSnapshot(position).getId();
Log.v("Firestore ID", recyclerPosition);
toClickedPoll.putExtra("POLL_ID", recyclerPosition);
startActivity(toClickedPoll);

}
});
}


@Override
public PollHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
return new PollHolder(v);
}


};
mRecyclerview.setAdapter(mFirestoreAdaper);
}
}


When I navigate to another Fragment (onClick of the RecyclerView) and then back to the Fragment containing this RecyclerView, I expect to be able to maintain the position that was clicked. However, this is not occurring. Below is the code I have tried to save the state, it is simply reverting back to the top item of the RecyclerView:



    @Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mRecyclerViewState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLERVIEW_STATE, mRecyclerViewState);

}


EDIT: The original Fragment is part of a ViewPager (I am testing it right now on the NewFragment):



    public class SectionPagerAdapter extends FragmentPagerAdapter {

public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TrendingFragment();
case 1:
return new FollowingFragment();
case 2:
return new NewFragment();
default:
return new TrendingFragment();
}
}






java android firebase android-recyclerview






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 15:44







tccpg288

















asked Nov 22 '18 at 2:55









tccpg288tccpg288

1,18211535




1,18211535













  • show the fragment transition code

    – Har Kal
    Nov 22 '18 at 2:57











  • it might happen you are loading a fresh fragment on every click

    – Har Kal
    Nov 22 '18 at 2:58











  • What exact code do you need to see? Thanks for the help

    – tccpg288
    Nov 22 '18 at 2:59











  • the code you use to transit from one fragment to another

    – Har Kal
    Nov 22 '18 at 2:59











  • It is in the holder, there is a click Listener

    – tccpg288
    Nov 22 '18 at 3:00



















  • show the fragment transition code

    – Har Kal
    Nov 22 '18 at 2:57











  • it might happen you are loading a fresh fragment on every click

    – Har Kal
    Nov 22 '18 at 2:58











  • What exact code do you need to see? Thanks for the help

    – tccpg288
    Nov 22 '18 at 2:59











  • the code you use to transit from one fragment to another

    – Har Kal
    Nov 22 '18 at 2:59











  • It is in the holder, there is a click Listener

    – tccpg288
    Nov 22 '18 at 3:00

















show the fragment transition code

– Har Kal
Nov 22 '18 at 2:57





show the fragment transition code

– Har Kal
Nov 22 '18 at 2:57













it might happen you are loading a fresh fragment on every click

– Har Kal
Nov 22 '18 at 2:58





it might happen you are loading a fresh fragment on every click

– Har Kal
Nov 22 '18 at 2:58













What exact code do you need to see? Thanks for the help

– tccpg288
Nov 22 '18 at 2:59





What exact code do you need to see? Thanks for the help

– tccpg288
Nov 22 '18 at 2:59













the code you use to transit from one fragment to another

– Har Kal
Nov 22 '18 at 2:59





the code you use to transit from one fragment to another

– Har Kal
Nov 22 '18 at 2:59













It is in the holder, there is a click Listener

– tccpg288
Nov 22 '18 at 3:00





It is in the holder, there is a click Listener

– tccpg288
Nov 22 '18 at 3:00












1 Answer
1






active

oldest

votes


















1














That's because you're setting new adapter in onStart, and that happens whenever you resume the fragment, either from previous screen or background.



You don't need all these logics to help to remember the position, you just have to initialise and set your adapter in the right place within the lifecycle.



In your fragment, set your adapter in onViewCreated instead of onStart:



@Override public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerview = view.findViewById(...);
if (mAdapter == null) {
mAdapter = new FirestoreRecyclerAdapter(...)
mRecyclerView.setAdapter(mAdapter);
mAdapter.startListening();
}
}

@Override public void onDestroyView() {
super.onDestroyView();
mAdapter.stopListening();
}


And remove all of your logics of saving and restoring position (onSaveInstanceState, scrollToPosition, onRestoreInstanceState), you don't need them!






share|improve this answer


























  • Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

    – tccpg288
    Nov 22 '18 at 3:37











  • @tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

    – Aaron
    Nov 22 '18 at 3:41











  • So I should delete from .onStart()?

    – tccpg288
    Nov 22 '18 at 3:46











  • You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

    – Aaron
    Nov 22 '18 at 3:52













  • Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

    – Aaron
    Nov 22 '18 at 4:01











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423236%2fcannot-maintain-firestore-recyclerview-state-on-back-navigation%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














That's because you're setting new adapter in onStart, and that happens whenever you resume the fragment, either from previous screen or background.



You don't need all these logics to help to remember the position, you just have to initialise and set your adapter in the right place within the lifecycle.



In your fragment, set your adapter in onViewCreated instead of onStart:



@Override public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerview = view.findViewById(...);
if (mAdapter == null) {
mAdapter = new FirestoreRecyclerAdapter(...)
mRecyclerView.setAdapter(mAdapter);
mAdapter.startListening();
}
}

@Override public void onDestroyView() {
super.onDestroyView();
mAdapter.stopListening();
}


And remove all of your logics of saving and restoring position (onSaveInstanceState, scrollToPosition, onRestoreInstanceState), you don't need them!






share|improve this answer


























  • Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

    – tccpg288
    Nov 22 '18 at 3:37











  • @tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

    – Aaron
    Nov 22 '18 at 3:41











  • So I should delete from .onStart()?

    – tccpg288
    Nov 22 '18 at 3:46











  • You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

    – Aaron
    Nov 22 '18 at 3:52













  • Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

    – Aaron
    Nov 22 '18 at 4:01
















1














That's because you're setting new adapter in onStart, and that happens whenever you resume the fragment, either from previous screen or background.



You don't need all these logics to help to remember the position, you just have to initialise and set your adapter in the right place within the lifecycle.



In your fragment, set your adapter in onViewCreated instead of onStart:



@Override public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerview = view.findViewById(...);
if (mAdapter == null) {
mAdapter = new FirestoreRecyclerAdapter(...)
mRecyclerView.setAdapter(mAdapter);
mAdapter.startListening();
}
}

@Override public void onDestroyView() {
super.onDestroyView();
mAdapter.stopListening();
}


And remove all of your logics of saving and restoring position (onSaveInstanceState, scrollToPosition, onRestoreInstanceState), you don't need them!






share|improve this answer


























  • Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

    – tccpg288
    Nov 22 '18 at 3:37











  • @tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

    – Aaron
    Nov 22 '18 at 3:41











  • So I should delete from .onStart()?

    – tccpg288
    Nov 22 '18 at 3:46











  • You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

    – Aaron
    Nov 22 '18 at 3:52













  • Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

    – Aaron
    Nov 22 '18 at 4:01














1












1








1







That's because you're setting new adapter in onStart, and that happens whenever you resume the fragment, either from previous screen or background.



You don't need all these logics to help to remember the position, you just have to initialise and set your adapter in the right place within the lifecycle.



In your fragment, set your adapter in onViewCreated instead of onStart:



@Override public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerview = view.findViewById(...);
if (mAdapter == null) {
mAdapter = new FirestoreRecyclerAdapter(...)
mRecyclerView.setAdapter(mAdapter);
mAdapter.startListening();
}
}

@Override public void onDestroyView() {
super.onDestroyView();
mAdapter.stopListening();
}


And remove all of your logics of saving and restoring position (onSaveInstanceState, scrollToPosition, onRestoreInstanceState), you don't need them!






share|improve this answer















That's because you're setting new adapter in onStart, and that happens whenever you resume the fragment, either from previous screen or background.



You don't need all these logics to help to remember the position, you just have to initialise and set your adapter in the right place within the lifecycle.



In your fragment, set your adapter in onViewCreated instead of onStart:



@Override public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerview = view.findViewById(...);
if (mAdapter == null) {
mAdapter = new FirestoreRecyclerAdapter(...)
mRecyclerView.setAdapter(mAdapter);
mAdapter.startListening();
}
}

@Override public void onDestroyView() {
super.onDestroyView();
mAdapter.stopListening();
}


And remove all of your logics of saving and restoring position (onSaveInstanceState, scrollToPosition, onRestoreInstanceState), you don't need them!







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 '18 at 20:47

























answered Nov 22 '18 at 3:33









AaronAaron

1,8132213




1,8132213













  • Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

    – tccpg288
    Nov 22 '18 at 3:37











  • @tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

    – Aaron
    Nov 22 '18 at 3:41











  • So I should delete from .onStart()?

    – tccpg288
    Nov 22 '18 at 3:46











  • You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

    – Aaron
    Nov 22 '18 at 3:52













  • Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

    – Aaron
    Nov 22 '18 at 4:01



















  • Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

    – tccpg288
    Nov 22 '18 at 3:37











  • @tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

    – Aaron
    Nov 22 '18 at 3:41











  • So I should delete from .onStart()?

    – tccpg288
    Nov 22 '18 at 3:46











  • You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

    – Aaron
    Nov 22 '18 at 3:52













  • Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

    – Aaron
    Nov 22 '18 at 4:01

















Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

– tccpg288
Nov 22 '18 at 3:37





Doesn't the FirestoreRecyclerAdapter need to be initialized in onStart() so that it can subscribe to the Firebase Firestore?

– tccpg288
Nov 22 '18 at 3:37













@tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

– Aaron
Nov 22 '18 at 3:41





@tccpg288 Nope, even though it is designed to be self-aware of lifecycle, but that doesn't mean it should be created in onStart.

– Aaron
Nov 22 '18 at 3:41













So I should delete from .onStart()?

– tccpg288
Nov 22 '18 at 3:46





So I should delete from .onStart()?

– tccpg288
Nov 22 '18 at 3:46













You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

– Aaron
Nov 22 '18 at 3:52







You should only init and set your adapter in onViewCreated, but I think you probably want to keep mAdapter.startListening in onStart, I'm not too familiar with Firebase adapter but I'm very sure that setting adapter should happen in onViewCreated.

– Aaron
Nov 22 '18 at 3:52















Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

– Aaron
Nov 22 '18 at 4:01





Actually, it's safe to remove every in onStart, you don't need to call mAdapter.startListening, it is already handled in the adapter. I hope!

– Aaron
Nov 22 '18 at 4:01




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423236%2fcannot-maintain-firestore-recyclerview-state-on-back-navigation%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()