Reset RecyclerView adapter from another Fragment - java

I have a Fragment that contains a RecyclerView. I am trying to implement a filter on the RecyclerView. The filter UI opens a new Fragment Dialog where the user will input a value. Once the user hits the Search Button in the Fragment Dialog, the value should be returned to the RecyclerView Fragment and the existing data in the view should be cleared. I want to re-populate the RecyclerView with the new set of data that I will obtain from the server. My problem is that, I have a method called resetAdapterDetails() in the RecyclerView Fragment which works as expected if called from the RecyclerView Fragment itself. But, when I try to call the same method from the Fragment Dialog, I get an exception:
transactionList.clear(); --> is trying to clear a list which is null
Though the data is still visible in the RecyclerView.
The RecyclerView Fragment:
public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener, DateRangePickerFragment.OnDateRangeSelectedListener{
private RecyclerView recyclerview;
private TransactionHistoryAdapter adapter;
private List<Transaction> transactionList;
public TransactionHistoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);
recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(layoutManager);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
getTransactionHistory("");
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.transactions_history_menu, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(this);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.filter_date:
FragmentManager fmDate = getActivity().getFragmentManager();
DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
dialogFragmentDate.show(fmDate, "Sample Fragment");
return true;
case R.id.filter_mobile:
FragmentManager fmMobile = getActivity().getFragmentManager();
SearchMobileFragment dialogFragmentMobile = new SearchMobileFragment ();
dialogFragmentMobile.show(fmMobile, "Sample Fragment");
//resetAdapterDetails();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onQueryTextChange(String newText) {
final List<Transaction> filteredModelList = filter(transactionList, newText);
adapter.setFilter(filteredModelList);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
//for filtering the list
private List<Transaction> filter(List<Transaction> models, String query) {
query = query.toLowerCase();final List<Transaction> filteredModelList = new ArrayList<>();
for (Transaction model : models) {
final String text = model.getTxnStatus().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
//for populating the list
private void getTransactionHistory(String agentId){
GetTransactionHistoryTask task = new GetTransactionHistoryTask("agent1", "password");
task.getTransactionsByAgent("OU23","OU230000000123456789").subscribe(transactionHistoryResponse -> {
if(transactionHistoryResponse != null && transactionHistoryResponse.getTransactions() != null && transactionHistoryResponse.getTransactions().size() > 0 && transactionHistoryResponse.getErrors().size() == 0){
transactionList = transactionHistoryResponse.getTransactions();
adapter = new TransactionHistoryAdapter(transactionList);
recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
recyclerview.setAdapter(adapter);
onClickListnerRecyclerView();
}
else{
}
}, e -> e.printStackTrace());
}
private void onClickListnerRecyclerView() {
recyclerview.addOnItemTouchListener(
new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
try {
final Transaction transactionModel= (Transaction) adapter.getObjectAt(position);
Intent i = new Intent(getActivity(), TransactionDetailsActivity.class);
i.putExtra("transaction_object",transactionModel);
startActivity(i);
}
catch (Exception e){
Log.e("List issue", e.toString());
}
}
})
);
}
#Override
public void onDateRangeSelected(int startDay, int startMonth, int startYear, int endDay, int endMonth, int endYear) {
}
public void fetchDateRange(String startDate, String endDate) {
Log.e("DateRange",startDate + "\n" + endDate);
}
public void fetchMobileNumber(String mobileNumber) {
Log.e("Mobile",mobileNumber);
resetAdapterDetails();
}
public boolean resetAdapterDetails(){
try {
transactionList.clear();
adapter.notifyDataSetChanged();
recyclerview.setAdapter(adapter);
} catch (Exception e) {
Log.e("Reset Error", ""+e.getMessage());
}
return true;
}
}
The Dialog Fragment:
public class SearchMobileFragment extends DialogFragment {
EditText mMobileNumberEditText;
Button search_button;
public SearchMobileFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search_mobile, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMobileNumberEditText = (EditText) view.findViewById(R.id.mobile_number_editText);
search_button = (Button) view.findViewById(R.id.search_button);
search_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
dismiss();
TransactionHistoryFragment obj = new TransactionHistoryFragment();
obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());
}
});
}
}
The fetchMobileNumber() method in the TransactionHistoryFragment (RecyclerView Fragment) is called through the fetchMobileNumber() method which is called from the SearchMobileFragment (Dialog Fragment).
Where am I going wrong? Why the transactionList.clear(); is throwing the null pointer exception?

You are getting the issue because you are creating new TransactionHistoryFragment instance search_button click in SearchMobileFragment. Which makes it's all variables null and initialize it again and here your transactionList becomes null.
You can achieve the same thing easily with different way also. As the place of SearchMobileFragment as a DialogFragment you can make it as Activity and start it as startActivityForResult from your TransactionHistoryFragment and implement onActivityResult callback to doing the fiteration.
But right now in your case you can manage it in different ways also:
First way:
As you are doing in your DialogFragment
search_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
dismiss();
/*TransactionHistoryFragment obj = new TransactionHistoryFragment();
obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());*/
}
});
Don't do the call for fetchMobileNumber here, in onResume of your TransactionHistoryFragment you should make a call for this. On the click of search_button save the filter data to SharedPreferences and use that in onResume of the TransactionHistoryFragment for filtering and after that clear this saved data from SharedPreferences onPause of this fragment.
You should remove
transactionList.clear();
of code from resetAdapterDetails() in TransactionHistoryFragment, because after search filter you will get updated transactionList which is already passed to adapter then forcefully no need to clear it. Or have a check before clearing it like:
if(transactionList!=null){
transactionList.clear();
}
Second way: Using BroadcastReceiver you can achieve the same thing.
Register a receiver in your TransactionHistoryFragment and sendBroadcast from SearchMobileFragment. In onReceive of the TransactionHistoryFragment do the filtration process.

I had resolved the above issue in a different way. In the Dialog Fragment I have implemented a View.OnClickListener and have created an Interface to initialize the same from the RecyclerView Fragment. I am posting the complete source codes below; the SearchMobileFragment now looks like:
public class SearchMobileFragment extends DialogFragment implements View.OnClickListener{
private OnMobileNumberSelectedListener onMobileNumberSelectedListener;
EditText mMobileNumberEditText;
Button mSearchButton;
public SearchMobileFragment() {
// Required empty public constructor
}
public static SearchMobileFragment newInstance(OnMobileNumberSelectedListener callback) {
SearchMobileFragment searchMobileFragment = new SearchMobileFragment();
searchMobileFragment.initialize(callback);
return searchMobileFragment;
}
public void initialize(OnMobileNumberSelectedListener callback) {
onMobileNumberSelectedListener = callback;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_search_mobile, container, false);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mMobileNumberEditText = (EditText) root.findViewById(R.id.mobile_number_editText);
mSearchButton = (Button) root.findViewById(R.id.search_button);
mSearchButton.setOnClickListener(this);
return root;
}
#Override
public void onStart() {
super.onStart();
if (getDialog() == null)
return;
getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
}
public void setOnMobileNumberSelectedListener(OnMobileNumberSelectedListener callback) {
this.onMobileNumberSelectedListener = callback;
}
#Override
public void onClick(View v) {
dismiss();
onMobileNumberSelectedListener.onMobileNumberSelected(mMobileNumberEditText.getText().toString());
}
public interface OnMobileNumberSelectedListener {
void onMobileNumberSelected(String mobileNumber);
}
}
The RecyclerView Fragment modifications:
public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener,
DateRangePickerFragment.OnDateRangeSelectedListener, SearchMobileFragment.OnMobileNumberSelectedListener{
private RecyclerView recyclerview;
private TransactionHistoryAdapter adapter;
private List<Transaction> transactionList;
SearchView search;
public static final String TIMERANGEPICKER_TAG = "timerangepicker";
public TransactionHistoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);
recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(layoutManager);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
getTransactionHistory();
}
#Override
public void onResume() {
Log.e("onResumeTHF","invoked");
super.onResume();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.transactions_history_menu, menu);
search = (SearchView) menu.findItem(R.id.action_search).getActionView();
search.setOnQueryTextListener(this);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.filter_date:
FragmentManager fmDate = getActivity().getFragmentManager();
DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
dialogFragmentDate.show(fmDate, "Sample Fragment");
return true;
case R.id.filter_mobile:
FragmentManager fmMobile = getActivity().getFragmentManager();
SearchMobileFragment dialogFragmentMobile = SearchMobileFragment.newInstance(this);
dialogFragmentMobile.show(fmMobile, "Sample Fragment");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onQueryTextChange(String newText) {
Log.e("newText",newText);
final List<Transaction> filteredModelList = filter(transactionList, newText);
adapter.setFilter(filteredModelList);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public void onMobileNumberSelected(String mobileNumber) {
Log.e("mobileNumber",mobileNumber);
resetAdapterDetails();
}
public boolean resetAdapterDetails(){
try {
transactionList.clear();
adapter.notifyDataSetChanged();
recyclerview.setAdapter(adapter);
} catch (Exception e) {
Log.e("Reset Error", ""+e.getMessage());
}
return true;
}
}
Happy coding!

The null pointer exception is because when you create a new TransactionHistoryFragment using new onViewCreated is not called and hence transactionList is never initialized. You can create a setter for the list or pass it as a constructor to the fragment to fix this

Related

Navigates to second fragment again by pressing back button previous data exists

I have two fragments and one activity (Main Activity). Now when I go from fragment 1 to fragment 2 data in fragment 2 loads from api. But when I press back button, navigates to fragment 1 and again I go from fragment 1 to fragment 2 then the previous loaded data is there for some secs and then fragment loads new data. Why it is so? I want that whenever I go to the fragment 2 it should reload again all the data (without showing the previous data for some secs first). Which method I should use?
Here is my onclick method from fragment 1 for navigating to fragment 2.
private void bind(FragmentUserInputFormBinding binding) {
binding.btnFetchOffer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
isAllFieldChecked = validateAllFields(binding);
if (isAllFieldChecked) {
Bundle bundle = new Bundle();
bundle.putString("appid", binding.etAppId.getText().toString());
bundle.putString("uid", binding.etUserId.getText().toString());
bundle.putString("token", binding.etToken.getText().toString());
OfferWallListFragment offerWallListFragment = new OfferWallListFragment();
offerWallListFragment.setArguments(bundle);
requireActivity().getSupportFragmentManager().beginTransaction()
.replace(((ViewGroup) requireView().getParent()).getId(), offerWallListFragment,"offerListFragment")
.setReorderingAllowed(true)
.addToBackStack("offerListFragment")
.commit();
}
}
});
}
Now I have my second fragment designed as follows fragment 2.
#AndroidEntryPoint
public class OfferWallListFragment extends BaseFragment<FragmentOfferWallListBinding> {
private RecyclerViewAdapter recyclerViewAdapter;
private int currentPage = FIRST_PAGE;
public OfferWallListFragment() {
// Required empty public constructor
}
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Objects.requireNonNull(((AppCompatActivity) requireActivity()).getSupportActionBar()).setTitle("Offers List");
initViewModel(FragmentOfferWallListBinding.bind(view));
}
#NonNull
#Override
protected FragmentOfferWallListBinding initBinding(#NonNull LayoutInflater inflater, #Nullable ViewGroup container) {
return FragmentOfferWallListBinding.inflate(inflater, container, false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_offer_wall_list, container, false);
}
private void initViewModel(FragmentOfferWallListBinding binding) {
OfferWallViewModel offerWallViewModel = new ViewModelProvider(this).get(OfferWallViewModel.class);
offerWallViewModel.getLiveData(currentPage).observe(getViewLifecycleOwner(), new Observer<OfferResponse>() {
#Override
public void onChanged(OfferResponse offerResponse) {
if (offerResponse != null) {
recyclerViewAdapter = new RecyclerViewAdapter();
recyclerViewAdapter.setOfferResponse(offerResponse);
binding.rvOfferData.setHasFixedSize(true);
binding.rvOfferData.setLayoutManager(new LinearLayoutManager(getContext()));
binding.rvOfferData.setAdapter(recyclerViewAdapter);
binding.rvOfferData.setVisibility(View.VISIBLE);
}
RecyclerViewPaginator recyclerViewPaginator = new RecyclerViewPaginator(binding.rvOfferData) {
#Override
public boolean isLastPage() {
return currentPage == offerResponse.getPages();
}
#Override
public void loadMore(int _currentPage) {
currentPage = _currentPage;
offerWallViewModel.getLiveData(Math.toIntExact(_currentPage));
}
};
binding.rvOfferData.addOnScrollListener(recyclerViewPaginator);
}
});
offerWallViewModel.getNetworkStateMutableLiveData().observe(getViewLifecycleOwner(), new Observer<NetworkState>() {
#Override
public void onChanged(NetworkState networkState) {
if (networkState == NetworkState.Companion.getLOADING()) {
binding.pbLoadingItems.setVisibility(View.VISIBLE);
} else if (networkState == NetworkState.Companion.getERROR()) {
Toast.makeText(getContext(), "Something went wrong, please check the parameters are filled perfectly", Toast.LENGTH_SHORT).show();
if (!CheckInternetConnection.isInternetAvailable(getContext())) {
Toast.makeText(getContext(), "No Internet Connection Available", Toast.LENGTH_SHORT).show();
binding.txtNoConnection.setText("No Internet Connection Available");
binding.txtNoConnection.setVisibility(View.VISIBLE);
}
binding.pbLoadingItems.setVisibility(View.GONE);
} else {
binding.pbLoadingItems.setVisibility(View.GONE);
}
}
});
}
}
Also I have handled onBackPressed method from MainActivity as follows.
#AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.userInputFormFragment, R.id.offerWallListFragment
).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}
}
#Override
public void onBackPressed(){
int count = getSupportFragmentManager().getBackStackEntryCount();
if(count == 0) {
super.onBackPressed();
} else {
getSupportFragmentManager().popBackStack();
}
}
}
Please have a look on it ?

SearchData Method resets query? Firebase Database Android

In general, the thing is, I have three fragments. In the second snippet, it gets the data provided, here's the code.
1)MyPostFragment.class
public class MyPostsFragment extends PostListFragment {
public MyPostsFragment() {}
#Override
public Query getQuery(DatabaseReference databaseReference) {
return databaseReference.child("songsDB")
.orderByChild("stars/" + getUid())
.equalTo(true);
}
2)PostListFragment
public abstract class PostListFragment extends Fragment {
private DatabaseReference mDatabase;
private FirebaseRecyclerAdapter mAdapter;
private RecyclerView mRecycler;
private Activity mActivity;
Query mRef;
SearchView searchView;
LinearLayoutManager mManager;
FirebaseDatabase mFirebaseDatabase;
public PostListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment_all_posts, container, false);
mRecycler = rootView.findViewById(R.id.messages_list);
mRecycler.setHasFixedSize(true);
mDatabase = FirebaseDatabase.getInstance().getReference();
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
// Set up Layout Manager, reverse layout
mManager = new LinearLayoutManager(getActivity());
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecycler.setLayoutManager(mManager);
Query postsQuery = getQuery(mDatabase);
ShowData(postsQuery);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
MenuItem item = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
SearchData(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
//Filter as you type
SearchData(newText);
return false;
}
});
super.onCreateOptionsMenu(menu,inflater);
}
private FirebaseRecyclerAdapter getMAdapter(Query query){
mActivity = getActivity();
final Dialog mDialog = new Dialog(mActivity, R.style.NewDialog);
mDialog.addContentView(
new ProgressBar(mActivity),
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
);
mDialog.setCancelable(true);
mDialog.show();
FirebaseRecyclerOptions<Post> options = new FirebaseRecyclerOptions.Builder<Post>()
.setQuery(query, Post.class)
.build();
mAdapter = new FirebaseRecyclerAdapter<Post, PostViewHolder>(options) {
#Override
protected void onBindViewHolder(PostViewHolder viewHolder, int position, final Post model) {
final DatabaseReference postRef = getRef(position);
// Determine if the current user has liked this post and set UI accordingly
if (model.stars.containsKey(getUid())) {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_24);
} else {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_outline_24);
}
if (!TextUtils.isEmpty(model.kzSongytblink))
viewHolder.mImage.setImageResource(R.drawable.on_line_logo);
else viewHolder.mImage.setImageResource(R.drawable.off_line_logo);
// Bind Post to ViewHolder, setting OnClickListener for the star button
viewHolder.bindToPost(model, new View.OnClickListener() {
#Override
public void onClick(View starView) {
// Need to write to both places the post is stored
DatabaseReference globalPostRef = mDatabase.child("songsDB").child(postRef.getKey());
// Run two transactions
onStarClicked(globalPostRef);
}
});
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mActivity, PostDetailActivity.class);
intent.putExtra(PostDetailActivity.EXTRA_POST_KEY, postRef.getKey());
startActivity(intent);
}
});
}
#Override
public PostViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
return new PostViewHolder(inflater.inflate(R.layout.item_post, viewGroup, false));
}
};
return mAdapter;
}
public void ShowData(Query postsQuery) {
mAdapter=getMAdapter(postsQuery);
mRecycler.setAdapter(mAdapter);
}
public void SearchData(String searchText){
//SearchData
mFirebaseDatabase = FirebaseDatabase.getInstance();
mRef = FirebaseDatabase.getInstance().getReference("songsDB");
Query postsQuery= mRef.orderByChild("kzSongTitle").startAt(searchText).endAt(searchText + "\uf8ff");
mAdapter=getMAdapter(postsQuery);
mRecycler.setAdapter(mAdapter);
}
#Override
public void onStart() {
super.onStart();
if (mAdapter != null) {
mAdapter.startListening();
}
}
#Override
public void onStop() {
super.onStop();
if (mAdapter != null) {
mAdapter.stopListening();
}
}
private void onStarClicked(DatabaseReference postRef) {
postRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Post p = mutableData.getValue(Post.class);
if (p == null) {
return Transaction.success(mutableData);
}
if (p.stars.containsKey(getUid())) {
// Unstar the post and remove self from stars
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
// Star the post and add self to stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
Log.d("postTransaction", "onComplete:" + dataSnapshot.getKey());
}
});
}
public String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
public abstract Query getQuery(DatabaseReference databaseReference);
}
If you remove the SearchData method, everything is loaded normally, but the searching is not working and I need it.
Without method SearchData :
If you don't remove SearchData load all data from database in all fragments.
I need to fix it, but I don't know how. Help me please.
With method SearchData :

Make detailed data from the recyclerview with intent in extends Fragment

Make detailed data from the recyclerview with intent in extends Fragment. what I know is using .putExtra, but I don't know how to write it in the fragment
public class NoteFragment extends Fragment {
private static final String TAG = NoteFragment.class.getSimpleName();
private RecyclerView recyclerView;
private NoteAdapter adapter;
private OnNoteFragmentListener listener;
public NoteFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_note, container, false);
recyclerView = view.findViewById(R.id.rv_notes);
FloatingActionButton fab = view.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
listener.onAddButtonClicked();
}
}
});
adapter = new NoteAdapter(getContext());
recyclerView.setAdapter(adapter);
listener.onNotesLoad(adapter);
displayAsGrid();
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_note, menu);
super.onCreateOptionsMenu(menu, inflater);
}
private void displayAsList() {
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
adapter.setLayout(Constant.LAYOUT_MODE_LIST);
}
private void displayAsGrid() {
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(layoutManager);
adapter.setLayout(Constant.LAYOUT_MODE_GRID);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_show_list:
displayAsList();
return true;
case R.id.action_show_grid:
displayAsGrid();
return true;
case R.id.action_logout:
Log.i(TAG, "Logout click");
if (listener != null) {
listener.onLogoutMenuClicked();
}
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnNoteFragmentListener) {
listener = (OnNoteFragmentListener) context;
} else {
throw new RuntimeException(context.toString()
+ "must implement OnNoteFragmentListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
public interface OnNoteFragmentListener {
void onNotesLoad(NoteAdapter adapter);
void onAddButtonClicked();
void onLogoutMenuClicked();
}
}
I want the data contained in the recyclerview to be displayed on the new activity page according to the recyclerview that I clicked with the command .putExtra where do I put the code?
If you want to start activity, you need to use Intent. Parameters for intent has to be passed in your click listener. More information how to start activity is here Start activity
And here is example how to use listener in RecyclerView

Android pass value from third fragment to first fragment

Here is my adapter
viewHolder.Edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
mAuth=FirebaseAuth.getInstance();
FirebaseFirestore firebaseFirestore=FirebaseFirestore.getInstance();
firebaseFirestore.collection("bookings").whereEqualTo("customer",mAuth.getUid())
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (DocumentSnapshot document : task.getResult()) {
currentUserId=document.getId();
Log.d("ID", String.valueOf(currentUserId));
}
StylistFragment servicesFragment = new StylistFragment();
AppCompatActivity activity = (AppCompatActivity) view.getContext();
Bundle bundle=new Bundle();
bundle.putString("userdocumentid",currentUserId);
servicesFragment.setArguments(bundle);
activity.getSupportFragmentManager().beginTransaction()
.replace(R.id.frameLayout, servicesFragment).addToBackStack(null).commit();
// change navigation item color of a fragment when button is clicked
((HomeActivity)view.getContext()).changeMenu(R.id.navigation_stylist);
}
});
}
});
this is my fragment where i am receiving value from third fragment to first fragment
public class StylistFragment extends Fragment {
private RecyclerView recyclerView;
private String docid;
CircleImageView stylistImg;
public StylistFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.stylist_recycler, container, false);
recyclerView=view.findViewById(R.id.stylistRecycler);
stylistImg=view.findViewById(R.id.stylistImg);
Bundle bundle=getArguments();
if(bundle!=null){
docid=bundle.getString("userdocumentid","");
Log.d("selectedDocumentId",docid);
}
try{
FirebaseFirestore db = FirebaseFirestore.getInstance();
try {
db.collection("stylist").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
try {
ArrayList<String> stylistId=new ArrayList<>();
for(DocumentSnapshot documentSnapshot:task.getResult()){
String id=documentSnapshot.getId();
stylistId.add(id);
}
StylistAdapter listAdapter = new StylistAdapter(task,docid,stylistId,stylistImg);
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(getContext(), R.drawable.divider));
recyclerView.addItemDecoration(dividerItemDecoration);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(listAdapter);
}catch (Exception e){
e.printStackTrace();
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
}catch (Exception e){
e.printStackTrace();
}
}catch (Exception e){
e.printStackTrace();
}
return view;
}
}
I am passing value from third fragment to first fragment.In third fragment i am using recyclerview if recyclerview excutes first item the value is available which i am getting in docid but if it executes more than one time the docid is null.Earlier i used the same code its worked fine i don't know what happend its not working now
Make use of interfaces.
Make a interface inside the third fragment and implement it in first fragment and call the function from third fragment with the value.
you can use the value in first fragment.
public class MainActivity extends AppCompatActivity {
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, StylistFragment.getInstannce("navigation_home")).addToBackStack(null).commit();
return true;
case R.id.navigation_dashboard:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, StylistFragment.getInstannce("navigation_dashboard")).addToBackStack(null).commit();
return true;
case R.id.navigation_notifications:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, StylistFragment.getInstannce("navigation_notifications")).addToBackStack(null).commit();
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
public static class StylistFragment extends Fragment {
private static final String TAG_VALUE = "tag_value";
public static StylistFragment getInstannce(String myValue){
Bundle extras = new Bundle();
extras.putString(TAG_VALUE,myValue);
StylistFragment fragment = new StylistFragment();
fragment.setArguments(extras);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String myStringValue = getArguments().getString(TAG_VALUE);
Log.d(TAG_VALUE, "My passed Value: " + myStringValue);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Output
D/tag_value: My passed Value: navigation_home
D/tag_value: My passed Value: navigation_dashboard
D/tag_value: My passed Value: navigation_notifications

Why is my android.R.id.home not called in my fragment?

I'm currently using FragmentStatePagerAdapter and I would like it to have a "navigate up" feature (DisplayHomeAsUpEnabled). When I set the following code it shows up as a correct navigate back button. But nothing happens when I click on it, can you guys see anything that I', doing wrong in my code, I get no error while pressing the "navigate up" button and I get no compiler errors.
Here is the code, its in the "public boolean onOptionsItemSelected(MenuItem item) {" it gets interesting at the bottom.
public class ShareholdingDetailFragment extends FragmentActivity {
final int NUM_ITEMS = Portfolio.getPortfolio().count();
MyAdapter mAdapter;
ViewPager mPager;
Bundle extras;
#Override
protected void onCreate(Bundle savedInstanceState) {
System.out.println(NUM_ITEMS + "e");
super.onCreate(savedInstanceState);
setContentView(R.layout.shareholdingdetailview_fragment_wrapper);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
}
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
public int getCount() {
return NUM_ITEMS;
}
public Fragment getItem(int position) {
return ShareholdingFragment.newInstance(position);
}
}
public static class ShareholdingFragment extends Fragment {
int mNum;
static ShareholdingFragment newInstance(int num) {
ShareholdingFragment f = new ShareholdingFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
#SuppressLint({ "NewApi", "NewApi" })
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.shareholdingdetailview_fragment, container, false);
/****************Setting the Display as home and it shows*******************/
ActionBar bar = getActivity().getActionBar();
bar.setDisplayHomeAsUpEnabled(true);
/**********************************/
return view;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home://Not working
System.out.println("test");//This isn't printed out
Intent upIntent = new Intent(getActivity(), DetailShareHoldingActivity.class);
if (NavUtils.shouldUpRecreateTask(getActivity(), upIntent)) {
getActivity().finish();
} else {
NavUtils.navigateUpTo(getActivity(), upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
Try adding: setHasOptionsMenu(true); in your onCreate() in ShareholdingFragment.
Add setHomeButtonEnabled(true) on API Level 14 and higher when you configure your action bar. On API Level 11-13, the home button is enabled automatically.
If you're using the new Toolbar and ActionbarDrawerToggle. You can assign clickHandler directly. For my activities that have this drawer toolbar I implemented an interface to enable drawer if at root,
#Override
public void enableDrawer(boolean enable) {
mDrawerToggle.setDrawerIndicatorEnabled(enable);
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Pop fragment back stack or pass in a custom click handler from the fragment.
}
});
}

Categories

Resources