Cannot Maintain Firestore RecyclerView State On Back Navigation
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
|
show 8 more comments
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
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 8 more comments
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
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
java android firebase android-recyclerview
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 8 more comments
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
|
show 8 more comments
1 Answer
1
active
oldest
votes
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!
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 inonStart
.
– 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 inonStart
, you don't need to callmAdapter.startListening
, it is already handled in the adapter. I hope!
– Aaron
Nov 22 '18 at 4:01
|
show 4 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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!
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 inonStart
.
– 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 inonStart
, you don't need to callmAdapter.startListening
, it is already handled in the adapter. I hope!
– Aaron
Nov 22 '18 at 4:01
|
show 4 more comments
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!
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 inonStart
.
– 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 inonStart
, you don't need to callmAdapter.startListening
, it is already handled in the adapter. I hope!
– Aaron
Nov 22 '18 at 4:01
|
show 4 more comments
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!
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!
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 inonStart
.
– 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 inonStart
, you don't need to callmAdapter.startListening
, it is already handled in the adapter. I hope!
– Aaron
Nov 22 '18 at 4:01
|
show 4 more comments
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 inonStart
.
– 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 inonStart
, you don't need to callmAdapter.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
|
show 4 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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