AM not so good in android Fragments. We need a proper solution to solve my problem. In mother activity I've fragment A,B,C. Every fragments comes after another . First A fragment is shown and after some user input we replace it with Fragment B and Fragment A is stacked. After B is done we replace it with C Fragment and B is stacked after A. I can go back to previous fragment to Edit the Data so we are saving the user inputs.
But when I go back to Fragments always I can get all data but only can update Fragment A UI view . I can't update any ui view in Fragment B and C .
Code snippests for different portions
abid hasan: getting current object for updating
City currentCity = cityManager.getCurrentCity();
updateViews(currentCity);
checking data for this object and updating views .
public static void updateViews(City currentCity){
Log.d(TAG , "updating views for city... "+currentCity.getCityName());
if (currentCity.getCityAccommodations().size() > 0 || currentCity.getCityLocations().size() > 0 || currentCity.getHotels().size() > 0) {
viewModifyLayoutHotels.setVisibility(View.VISIBLE);
deSelectAccommodationRadioButton.setChecked(false);
} else {
viewModifyLayoutHotels.setVisibility(View.GONE);
}
if (currentCity.cityFlights.size() > 0) {
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
} else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if(currentCity.getFlightClass().equals("")){
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
}else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if (currentCity.getActivities().size() > 0) {
viewModifyLayoutActivities.setVisibility(View.VISIBLE);
deSelectActivityRadioButton.setChecked(false);
} else {
viewModifyLayoutActivities.setVisibility(View.GONE);
}
}
on back press event from the successor fragment’s onDestroy() method and getting that object from manager and updating views
public static void updateViews(City currentCity){
Log.d(TAG , "updating views for city... "+currentCity.getCityName());
if (currentCity.getCityAccommodations().size() > 0 || currentCity.getCityLocations().size() > 0 || currentCity.getHotels().size() > 0) {
viewModifyLayoutHotels.setVisibility(View.VISIBLE);
deSelectAccommodationRadioButton.setChecked(false);
} else {
viewModifyLayoutHotels.setVisibility(View.GONE);
}
if (currentCity.cityFlights.size() > 0) {
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
} else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if(currentCity.getFlightClass().equals("")){
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
}else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if (currentCity.getActivities().size() > 0) {
viewModifyLayoutActivities.setVisibility(View.VISIBLE);
deSelectActivityRadioButton.setChecked(false);
} else {
viewModifyLayoutActivities.setVisibility(View.GONE);
}
}
before onDestroy() call I reset Those view to initial state from onStart() method
#Override
public void onStart() {
Log.d(MakeATripStepFourFragment.TAG , "calling onStart from "+TAG);
MakeATripFragmentFirstTime.destinationTextView.setText("Select experts for your trip");
resetCityPreferencesViews();
super.onStart();
}
public static void resetCityPreferencesViews() {
MakeATripStepFourFragment.deSelectFlyRadioButton.setChecked(true);
MakeATripStepFourFragment.selectFlyRadioButton.setChecked(false);
MakeATripStepFourFragment.deSelectAccommodationRadioButton.setChecked(true);
MakeATripStepFourFragment.selectAccommodationRadioButton.setChecked(false);
MakeATripStepFourFragment.deSelectActivityRadioButton.setChecked(true);
MakeATripStepFourFragment.selectActivityRadioButton.setChecked(false);
MakeATripStepFourFragment.viewModifyLayoutFlights.setVisibility(View.GONE);
MakeATripStepFourFragment.viewModifyLayoutHotels.setVisibility(View.GONE);
MakeATripStepFourFragment.viewModifyLayoutActivities.setVisibility(View.GONE);
}
for that city for those UI is not updating I use a LocalBroadcast call to Separate UI thread updating
if (!childFragment.onBackPressed()) {
// child Fragment was unable to handle the task
// It could happen when the child Fragment is last last leaf of a chain
// removing the child Fragment from stack
Log.d(MakeATripStepFourFragment.TAG , "this fragment.. "+childFragment.getClass().getSimpleName());
if(childFragment instanceof MakeATripStepFourFragment){
Log.d(MakeATripStepFourFragment.TAG ,"lets try it out");
if (cityManager.hasNextCity()) {
City currentCity = cityManager.getNextCity();
MakeATripFragmentFirstTime.destinationTextView.setText(currentCity.getCityName());
Log.d(MakeATripStepFourFragment.TAG, "updating radioButton with city.. "+currentCity.getCityName());
Intent intent = new Intent("update_radio-button");
intent.putExtra(MakeATripStepFourFragment.TAG,currentCity);
LocalBroadcastManager.getInstance(((MakeATripStepFourFragment) childFragment).getActivity()).sendBroadcast(intent);
}
}
childFragmentManager.popBackStackImmediate();
}
// either this Fragment or its child handled the task
// either way we are successful and done here
return true;
}
and in the broadcast receiver i call the updateViews() method
private BroadcastReceiver updatePreferences = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
City currentCity = (City) intent.getSerializableExtra(TAG);
Log.d(TAG , "recived call with city..."+currentCity.getCityName());
ExpertSelectorFragment.resetCityPreferencesViews();
updateViews(currentCity);
}
};
What maybe the solution I have to know . Please wanting perfect suggestion
Here on a button click looping through the city objects and adding fragment for them , if all city traversing completed then proceed to the next fragmet
case R.id.next_fragment_destination_button:
if (!cityManager.hasNextCity()) {
Log.d("status = ", "all city explored : " + cityManager.currentCityIndex);
cityManager.currentCityIndex = 0;
/*LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(messageReceiver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(accomodationAllPreferenceReciver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(activitiesForCityPreferenceReciver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(updatePreferences);*/
setDataToGetExperts(cityManager.getAllCities().size());
} else {
Log.d("status = ", "going to next : " + cityManager.currentCityIndex);
Log.d(TAG, "current city size " + cityManager.getCurrentCity().toString());
cityManager.getNextCity();
//we have a next city
MakeATripStepFourFragment fragment = MakeATripStepFourFragment.newInstance(0);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
// Store the Fragment in stack
transaction.addToBackStack(null);
transaction.replace(R.id.fragment_holder, fragment ,TAG);
transaction.commit();
}
break;
Related
I have the following situation:
I have activity and several fragments. At the beginning of the onCreate method I always load the fragment present in the picture above:
private void setInitialFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
DietDiaryFragment dietDiaryFragment = (DietDiaryFragment) fragmentManager.findFragmentByTag("DietDiaryFragment");
if (dietDiaryFragment == null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
dietDiaryFragment = new DietDiaryFragment();
setArguments(dietDiaryFragment);
fragmentTransaction.add(R.id.content_main_screen, dietDiaryFragment,"DietDiaryFragment");
fragmentTransaction.commit();
}
}
Where the setArguments method is as follows:
private void setArguments(DietDiaryFragment dietDiaryFragment) {
Bundle bundle = new Bundle();
bundle.putParcelable("breakfast", breakfast);
bundle.putParcelable("lunch", lunch);
bundle.putParcelable("dinner", dinner);
bundle.putParcelable("snacks", snacks);
dietDiaryFragment.setArguments(bundle);
}
In activity, I download from Firebase all products from a given meal, depending on the date and send it to the fragment where I showed above:
private void getProductsFromDatabaseLunch() {
lunch.getTotalProducts().clear();
lunch.getIdProducts().clear();
lunch.setTotalCalories(0);
firebaseFirestore.collection("Users").document(currentUserUID)
.collection("Types of Meals").document("Lunch")
.collection("Date of Lunch").document(date)
.collection("List of Products")
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()) {
for(DocumentSnapshot documentSnapshot: task.getResult().getDocuments()) {
lunch.getIdProducts().add(documentSnapshot.getId());
lunch.getTotalProducts().add(documentSnapshot.toObject(Product.class));
}
lunch.calculateTotalCalories();
onSendTotalCaloriesLunch.sendTotalCaloriesLunch(lunch.getTotalCalories());
}
if(getFragmentRefreshLunchAdapter() != null) {
getFragmentRefreshLunchAdapter().refreshLunchAdapter();
}
}
});
}
Downloading products from Firebase is asynchronous, so first empty ArrayLists without products will be passed, only after a while products are added.
To perform some calculations and display the results obtained, I used ObservableList, which informs me that the products have been downloaded from Firebase.
observableProductListSnacks.addAll(snacks.getTotalProductsOfMeal());
Method onChanged:
observableProductListBreakfast.addListener(new ListChangeListener<Product>() {
#Override
public void onChanged(Change<? extends Product> change) {
Log.i("Calories 1", String.valueOf(breakfast.getTotalCaloriesOfMeal()));
breakfast.calculateTotalCarbohydratesOfMeal();
breakfast.calculateTotalProteinOfMeal();
breakfast.calculateTotalFatOfMeal();
breakfast.calculateTotalCaloriesOfMeal();
Log.i("Calories 2", String.valueOf(breakfast.getTotalCaloriesOfMeal()));
if(breakfast.getTotalProductsOfMeal().size() == 0) {
textViewTotalCaloriesBreakfast.setText("");
} else {
textViewTotalCaloriesBreakfast.setText(product.formatNumberWithoutDecimalPlaces(breakfast.getTotalCaloriesOfMeal()));
}
}
});
The problem is that when I extend the calendar and navigate between days, products will constantly be added to observableProductListSnacks. Therefore, after changing the day I try to clear observableProductListSnacks, but ... then the onUpdate method is executed twice. Is there any way to avoid this? Or is it not a problem that the products build up on different days in observableProductListSnacks? Or it is not a problem that the onUpdate method is executed twice, because i clear observableProductListSnacks and then download products from new day ?
After watching this video by the firestore team :
https://www.youtube.com/watch?v=kDZYIhNkQoM
I have tried to implement the "this" listener before "new" keyword at "OnSuccess"
As an example:
public void pullEventsFromDatabase() {
mEventRef.get().addOnSuccessListener(getActivity(), new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
if (documentSnapshots.size() <= 0) {
setNothingToShow();
Log.w(TAG, "Error getting documents. Cat might be empty");
} else {
events.clear();
for (DocumentSnapshot document : documentSnapshots) {
Event event = document.toObject(Event.class);
events.add(new Event(event.getImageUrl(), event.getTitle(), event.getSummary(), event.getembeddedIDOrPowerLinkID(), event.getLinkToEvent(), event.getLinkToFastReservation(), event.getKey(), event.getDateOfPublish()));
}
if (events != null) {
Collections.sort(events);
initEventsRecyclerView();
}
}
}
});
}
Instead of "this" I'm using the context which is "getActivity" as this function is executed at onCreateView in a fragment.
Unfortunately while trying to implement this method (only with the context, without it the function works, but it has a bit different effect) The fragment transaction breaks!
Trying to navigate between fragments will work at start but after 2 - 3 times of going through the same fragment will cause the fragment transaction to break completely and stop responding until the app will call onDestroy and onCreate again.
Thanks in advance.
At the beginning of the chat app user see a list off groups (listview group) available and the user have the possibility to create a new group or click on some off the available groups and then start to write messages (listview messages). The functions CreateNewMessage and CreateNewGroup pushes information to firebase correctly
Above scenarios works finne problems arise when user navigates backwards (popBackStack()) from listview with messages to GroupFragment, here should user be presented a list off available groups but the listview is empty. The ReadGroupData() function is not reading the already created groups from firebase and inserts them in the group listview. How to make this happen?
GroupFragment:
public void ReadGroupData() {
Firebase firebaserootRef = new Firebase("https://000.firebaseio.com");
firebaserootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.getValue() != null) {
Group newGroup = new Group((String)snapshot.child("name").getValue(),
(String) snapshot.child("id").getValue());
if(!groupKeyValues.contains(newGroup.GetId())) {
groupKeyValues.add(newGroup.GetId());
AddToLstViewGroup(newGroup);
System.out.println("Read group data from firebase and
inserted in listView");
}
}
}
});
}
public void AddToLstViewGroup(Group newGroup) {
groupNameList.add(newGroup);
if(groupAdapter == null) {
groupAdapter = new GroupAdapter(getActivity(), groupNameList);
}
if (lstViewGroup == null) {
lstViewGroup = (ListView) getView().
findViewById(R.id.listView_group);
}
lstViewGroup.setOnItemClickListener(onItemClickListener);
lstViewGroup.setOnItemLongClickListener(onItemLongClickListener);
groupAdapter.notifyDataSetChanged();
lstViewGroup.setAdapter(groupAdapter);
}
ChatFragment:
public void ReadChatMessages(Firebase firebaseRootRef) {
firebaseRootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.child(GetGroupId()).child("messages").
getChildren() != null) {
for (DataSnapshot c :
snapshot.child(GetGroupId()).child("messages").getChildren()) {
String key = c.getKey();
Message newMessage = new Message();
newMessage.SetFrom((String) c.child("from").getValue());
newMessage.SetMsg((String)
c.child("message").getValue());
newMessage.SetTime((String) c.child("time").getValue());
newMessage.SetId((String) c.child("id").getValue());
if ((!msgKeyValues.contains(key)) ||
newMessage.GetFrom() != "") {
msgKeyValues.add(key);
AddToLstViewChat(newMessage);
//Automatic scrolls to last line in listView.
lstViewChat.setSelection(chatAdapter.getCount() -1);
}
}
}
}
public void AddToLstViewChat(Message newMessage) {
chatMsgList.add(newMessage);
if (chatAdapter == null) {
chatAdapter = new ChatAdapter(getActivity(), chatMsgList);
}
if(IsMsgFromMe(newMessage)) {
lstViewChat = (ListView)
getView().findViewById(R.id.listView_chat_message_me);
} else {
lstViewChat =
(ListView)getView().findViewById(R.id.listView_chat_message_others);
}
chatAdapter.notifyDataSetChanged();
lstViewChat.setAdapter(chatAdapter);
}
ChatActivity:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
finish();
}
}
For all the code click on the link: "http://pastebin.com/97nR68Rm"
SOLUTION!
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for lstViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view, To clarifying:
Deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced with:
ListView lstViewGroup=(ListView)getView().findViewById(R.id.listView_group);
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for listViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view.
To clarify:
I deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced it with:
ListView lstViewGroup =(ListView)getView().findViewById(R.id.listView_group);
(The original asker posted the answer as part of the question. I'm copying it here as a matter of housekeeping.)
I am trying to make a wizard using Roman Nurik's library (https://plus.google.com/113735310430199015092/posts/6cVymZvn3f4).
I am having trouble accessing the collected data from the Review Fragment.
I made mCurrentReviewItems public in ReviewFragment and then I tried it like this
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mPager.getCurrentItem() == mCurrentPageSequence.size()) {
ReviewFragment reviewFragment = (ReviewFragment) mPagerAdapter.getItem(mPager.getCurrentItem());
for (ReviewItem item : reviewFragment.mCurrentReviewItems)
Log.d(MainActivity.TAG, "Item: " + item.getDisplayValue());
}
} else {
if (mEditingAfterReview) {
mPager.setCurrentItem(mPagerAdapter.getCount() - 1);
} else {
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
}
}
}
});
However its always null.
Inside if (mPager.getCurrentItem() == mCurrentPageSequence.size()) { }
For single page variable:
String data = mWizardModel.findByKey("Sandwich:Bread").getData().getString(Page.SIMPLE_DATA_KEY);
For customized page:
String data =
mWizardModel.findByKey(THE_KEY).getData().getString(CustomerInfoPage.YOUR_DATA_KEY);
If you want to assign the data back to the wizard, put this at the end of onCreate in FragmentActivity:
Bundle data = new Bundle();
if (!TextUtils.isEmpty(DATA_STRING)) {
data.putString(Page.SIMPLE_DATA_KEY, DATA_STRING);
mWizardModel.findByKey("Sandwich:Bread"").resetData(data);
}
The key "Sandwich:Bread" is from the example, change whatever suit you. Never try the multi one, I think it is more or less the same.
Sorry for big delay, but I think that someone will found this info useful. I found a way to get all ReviewItems since you can have a lot of branches and you won't be able to use the first answer.
I'm pretty sure, that your mPagerAdapter::getItem code looked like in example (so it just returned new fragment, instead of returning current pager fragment). You have to use instantiateItem to get reference on your ReviewFragment.
Object o = mPager.getAdapter().instantiateItem(mPager, mPager.getCurrentItem());
if(o instanceof ReviewFragment) {
List<ReviewItem> items = ((ReviewFragment) o).getCurrentReviewItems();
if(items != null) {
Log.v(TAG, "Items are: " + items.toString());
}
}
This is my code #Anton_Shkurenko
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mPager.getCurrentItem() == mCurrentPageSequence.size()) {
Object o = mPager.getAdapter().instantiateItem(mPager, mPager.getCurrentItem());
if(o instanceof ReviewFragment) {
List<ReviewItem> items = ((ReviewFragment) o).getCurrentReviewItems();
if(items != null) {
Log.v(TAG, "Items are: " + items.toString());
}
}
}
}
});
The best solution is to include this library in your project as module, and implement your own method for getting review items in ReviewFragment.
public List<ReviewItem> getReviewItems() {
return mCurrentReviewItems;
}
I am not sure why developer did not add that. It's the most important thing in project. Choose items and DO something with them.
Anyone still looking for a solution for this issue you can use following code
ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
for (Page page : mWizardModel.getCurrentPageSequence()) {
page.getReviewItems(reviewItems);
}
I have a single fragment loaded in an activity using fragment manager inside a container layout. Inside my activity i start a service to connect to other bluetooth device and communicate with it by sending and receiving certain data. Everything works fine when the app is open and the service is connected to bluetooth device.
But when i hit back button and reopen my app , though my service is still connected to other bluetooth device the fragment i'm using to display the same shows it is in disconnected state.
I put a check before setting the text to my fragment's child textview using
fragment.isVisible()
and it returned false (?)
So , i think if i'm not wrong , the activity is creating a different instance of fragment over my original fragment everytime i open the app.
Here is the onCreate() of my activity..
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt_dashboard);
System.out.println("OnCreate() of BTDashboardActivity........");
if (findViewById(R.id.fragmentContainer) != null) {
if (savedInstanceState != null) {
System.out.println("ListFragmetn allready exist...");
return;
}
System.out.println("adding listfragment to view...");
listFragment = new BTDashboardListFragment();
listFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(R.id.fragmentContainer, listFragment).commit();
}
}
EDIT
here is code for onStart() of activity..
#Override
public void onStart() {
super.onStart();
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,
Constants.REQUEST_ENABLE_BT);
} else {
if (mBluetoothService == null) {
startBluetoothService();
Log.d(TAG, "Chat service Started...############");
showDisconnectedUI();
System.out.println("showing disconnceted status to the user..");
} else {
if (mBluetoothService.getState() == Constants.STATE_CONNECTED) {
System.out.println("showing connection status to the user..");
showConnectedUI();
} else {
System.out.println("showing disconnceted status to the user..");
showDisconnectedUI();
}
}
}
}
And this is code to set data to fragment's child views..
protected void handleResponse(String readMessage) {
System.out.println("response from device: " + readMessage);
if (readMessage != null) {
if (listFragment != null && listFragment.isInLayout()) {
System.out.println("List fragment is found...");
System.out.println("Setting response text to listFragment...");
if(listFragment.isVisible()) // prints not visible after reopening the app
System.out.println("listFragment is visible ...");
else
System.out.println("listFragment is not visible...");
listFragment.setResponseText(readMessage);
}
}
Any help is appreciated..
Making the fragment instance static solved my problem.
I know this is just a workaround
but works like a charm for me right now..