My database (Firestore) stores Chart
s, created by User
s.
On opening the app, the User
is shown their own Charts
, sorted by Chart Name (this is displayed in a Fragment called MyChartsFragment
). They can click a button to change the sort field; this should retrieve the same list of Charts
, but sorted by the selected field.
I'm able to pass the new sort field name into MyChartsFragment
, but at that point the list of Charts
goes blank. I assume I need to redraw it somehow.
The MyChartsFragment
is as follows (I've removed most of the try-catch blocks, error checks etc, for clarity):
public class FragmentMyCharts extends FragmentChartsList {
public FragmentMyCharts() {}
public Query getQuery(FirebaseFirestore databaseReference, String orderBy) {
// Specify the query which is used to retrieve this user's charts
return databaseReference.collection("charts")
.whereEqualTo("uid", getUid())
.orderBy(orderBy);
}
}
This extends FragmentChartsList
, which contains:
public abstract class FragmentChartsList extends Fragment {
private FirebaseFirestore mDatabaseRef;
private FirestoreRecyclerAdapter<Chart, ChartViewHolder> mAdapter;
private Query mChartsQuery;
private RecyclerView mRecycler;
private String mOrder = "name";
FragmentManager mFragmentManager;
ToolbarFragmentListCharts mFragmentTLC;
public FragmentChartsList() {}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// Inflate layout, and find Recycler View to hold the list
View rootView = inflater.inflate(
R.layout.fragment_charts_list, container, false);
mRecycler = rootView.findViewById(R.id.charts_list);
mRecycler.setHasFixedSize(true);
// Set up Layout Manager, and set Recycler View to use it
LinearLayoutManager mManager = new LinearLayoutManager(getActivity());
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecycler.setLayoutManager(mManager);
// Connect to the database, and get the appropriate query
mDatabaseRef = FirebaseFirestore.getInstance();
mChartsQuery = getQuery(mDatabaseRef, mOrder);
// Set up Recycler Adapter
FirestoreRecyclerOptions<Chart> recyclerOptions = new FirestoreRecyclerOptions.Builder<Chart>()
.setQuery(mChartsQuery, Chart.class)
.build();
mAdapter = new ChartListAdapter(recyclerOptions, this.getActivity());
// Use Recycler Adapter in RecyclerView
mRecycler.setAdapter(mAdapter);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Add listener to charts collection, and deal with any changes by re-showing the list
mChartsQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
@Nullable FirebaseFirestoreException e) {
if (queryDocumentSnapshots != null && queryDocumentSnapshots.isEmpty()) {
((MainActivity) Objects.requireNonNull(getActivity())).setPage(1);
}
}
});
}
@Override
public void onStart() {
super.onStart();
mAdapter.startListening();
}
public void setOrderField(String order) {
mOrder = order;
mChartsQuery = getQuery(mDatabaseRef, mOrder);
// Set up Recycler Adapter
FirestoreRecyclerOptions<Chart> recyclerOptions = new FirestoreRecyclerOptions.Builder<Chart>()
.setQuery(mChartsQuery, Chart.class)
.build();
mAdapter = new ChartListAdapter(recyclerOptions, this.getActivity());
// Use Recycler Adapter in RecyclerView
mRecycler.setAdapter(mAdapter);
}
public abstract Query getQuery(FirebaseFirestore databaseReference, String orderBy);
}
So, when the main activity is notified by the toolbar that the sort field has changed, it retrieves the MyChartsFragment (as a FragmentChartsList) and calls the setOrderField function:
public void setOrder(String order) {
FragmentChartsList myCharts = (FragmentChartsList) mPagerAdapter.getItem(0);
myCharts.setOrderField(order);
}
This appears to update the value of mOrder correctly, but then it doesn't re-display the RecyclerView, so I just get a blank space.
What am I doing wrong?
EDITED TO ADD DETAIL:
My ChartListAdapter
class is:
public class ChartListAdapter
extends FirestoreRecyclerAdapter<Chart, ChartViewHolder> {
private Activity mActivity;
private FirestoreRecyclerOptions<Chart> recyclerOptions;
public ChartListAdapter(FirestoreRecyclerOptions<Chart> recyclerOptions, Activity activity) {
super(recyclerOptions);
mActivity = activity;
}
@Override
protected void onBindViewHolder(@NonNull ChartViewHolder holder, int position, @NonNull Chart model) {
final String chartKey = this.getSnapshots().getSnapshot(position).getId();
model.setKey(chartKey);
// Set click listener for the chart
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mActivity, ActivityViewChart.class);
intent.putExtra("ChartKey", chartKey);
mActivity.startActivity(intent);
}
});
// Implement long-click menu
mActivity.registerForContextMenu(holder.itemView);
// Bind Chart to ViewHolder
holder.bindToChart(model);
}
@NonNull
@Override
public ChartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_chart, parent, false);
return new ChartViewHolder(view);
}
public void setRecyclerOptions(FirestoreRecyclerOptions<Chart> recyclerOptions) {
this.recyclerOptions = recyclerOptions;
}
}
Solved... in setOrderField
I was declaring a new mAdapter
, but not listening to it. Once I added
mAdapter.startListening()
it all worked fine!