Create a fragment and send data to it - android

Here is what I do to create a new fragment (called AlbumsTrackFragment) and replace the existing one :
AlbumsTrackFragment albumstrackfragment = new AlbumsTrackFragment();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.layout_ipod, albumstrackfragment, "albumsTrackfragment");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
albumstrackfragment.DoTask(data);
The problem is that when I can't call the method DoTask() and pass the new fragment some data because the app crashes, indeed I get : Content view not yet created
How can I wait that the commit was performed to call DoTask() method of my fragment ?
Thanks

You might consider passing in data to your fragment through DoTask and then wait until OnActivityCreated() is called to perform whatever action happens in DoTask. This way you are passing in your data but not doing anything until your view is loaded and won't crash.

Related

onCreateView from Fragment not called

I am refactoring an Android App to use fragments. I have a fragment which I add to the layout with transaction.replace method but whose onCreateView method is not called. Code looks as follows:
FragmentManager fragmentManager = m_Activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
m_StartNewGameFragment = new StartNewGameToggleButtonsFragment();
fragmentTransaction.replace(R.id.bottom_pane, m_StartNewGameFragment);
fragmentTransaction.commit();
String winnerText = null;
if (isComputerWinner)
winnerText = m_Activity.getResources().getText(R.string.computer_winner).toString();
else
winnerText = m_Activity.getResources().getText(R.string.player_winner).toString();
m_StartNewGameFragment.updateStats(computerWins, playerWins, winnerText);
The method updateStats of fragment is as follows:
public void updateStats(int computer_wins, int player_wins, String winnerText) {
System.out.println("Update stats " + m_ComputerWins);
m_ComputerWins.setText(Integer.toString(computer_wins));
m_PlayerWins.setText(Integer.toString(player_wins));
m_WinnerTextView.setText(winnerText);
}
When updateStats is called m_ComputerWins is null and the program crashes. m_ComputerWins is initialized inside the onCreateView method of the fragment which seems not to be called.
Can anyone please help ?
Take global variables in your fragment class for computer_wins, player_wins, winnerText and init them inside updateStats method.
then inside onViewCreated() method, set values like
m_ComputerWins.setText(Integer.toString(computer_wins));
m_PlayerWins.setText(Integer.toString(player_wins));
m_WinnerTextView.setText(winnerText);
You never know when the fragments is created (which calls onCreate()), because fragment's life cycle differs from your activity's. In your code, you are trying to update fragment from activity. But in the way you have written your code, it is almost guaranteed that your fragment is not created yet.
Search for how to pass parameters to fragment or update fragment to find out the correct way of updating fragment from activity. You can find several related question, e.g. this one.
FragmentTransaction only runs on the next event loop. If you want to immediately run a fragment transaction, use fragmentTransaction.commitNowAllowingStateLoss();.
Please note that this won't actually work correctly after process death, which is why you should use the fragment.setArguments(Bundle method to pass initial argument values to a fragment.

How to transfer data from one activity to a fragment with Firebase?

Hey I was wondering how I could transfer data from one activity to a fragment using fire base. I have edit text in the activity class and a list view in the Fragment.
I would like to display the information throughout the app database so that other users can see and edit the information too.
I dont know if the IDE matters but passing information to a fragment is usually done with fragment arguments. You need to create a static "newInstance" method in your fragment that you can call from the activity and pass whatever info to the fragment through it. Something like this:
public static mListFragment newInstance(String fromActivity) {
mListFragment fragment = new mListFragment ();
Bundle args = new Bundle();
args.putString("STIRNG_FROM_ACTIVITY", fromActivity);
fragment.setArguments(args);
return fragment;
}
You can then call the method from the activity like this:
FragmentManager fm = getFragmentManager().beginTransaction();
mListFragment fragment = new mListFragment();
fragment = mListFragment.newInstance("info_to_send");
fragmentTransaction.add(R.id.fragments_frame, fragment);
From here you can even persist the info across device screen orientation changes..
Just use firebaseRef to setValue() and set the value from the edittext.
Add ValueListener on the fragment to get the same value from dataSnapshot.
:D
https://github.com/firebase/quickstart-java/tree/master/database/src/main/java/com/google/firebase/quickstart

Update fragment from Activity from different thread

I'm very new to Androind, trying to figure how fragment and activity should be work together. I have a very ugly layout. 1 activity and 1 "root" fragment. When user click on left menu fragment are replaced by fragment manager.
expandableList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) {
LeftMenuItem group = groups.get(i);
String fragmentTag = group.getFragmentTag();
if (fragmentTag.equals(Fragment1.TAG)) {
Fragment1 fragment = (Fragment1) currentFragmentManager.findFragmentByTag(Fragment1.TAG);
if (fragment == null) {
fragment = new Fragment1();
}
FragmentTransaction ft = currentFragmentManager.beginTransaction();
ft.replace(R.id.root_frame, fragment, Fragment1.TAG);
ft.commitAllowingStateLoss();
} else if (fragmentTag.equals(Fragment2.TAG)) {
I assume code above is supposed to replace current fragment with new one. Fragments are always null actually. I do not know why.
In onCreateView of RootFragment Fragment1 is created by default.
if (savedInstanceState == null) {
Log.d(TAG, "savedInstanceState is null, creating Framgent1");
Fragment1 fragment = new Fragment1();
FragmentTransaction ft = currentFragmentManager.beginTransaction();
ft.replace(R.id.root_frame, fragment, Fragment1.TAG);
ft.commitAllowingStateLoss();
}
In onCreateView of rootFragment, rootFragment replaces itself with another Fragment1, which looks very ugly for me. Is it well known Androind pattern or just bad design ?
Let's assume that'm sending httpRequest from onCreateView of MyActivity using Volley. Once I received response I need to update Fragment1 UI from callback. How can I do it ?
Should I try to find fragment using findFragmentByTag in my activity and update UI directly ? Is http volley response is in the same thread ? If no, it is ok to update UI from different thread ?
Should I use a Handler class to send message from Activity to Fragment ?
Should I try to find fragment using findFragmentByTag in my activity and update UI directly ? Is http volley response is in the same thread ? If no, it is ok to update UI from different thread ?
findFragmentByTag will not be useful since as soon as replace is
called, the previous fragment is destroyed. If you have only few
fragment you want to switch, you can use hte below solution :
How can I switch between two fragments, without recreating the fragments each time?
Answer to second part of your question 1 :
Volley response is always called on the main thread to its perfectly
ok to update UI on the callback. You should never update UI elements
on any thread other than MAIN / UI thread.
Should I use a Handler class to send message from Activity to Fragment ?
You can choose to send the message by handler but if usually android documentation suggests to send communicate between activity and attached fragments via callbacks
https://developer.android.com/training/basics/fragments/communicating.html

call fragment method but fragment not prepared complitily

I want to dynamically create fragment. So when click the navigation fragment item, it will trigger the callback function in the activity to communicate with detail fragment. Here is the callback faction in activity:
public void getChatRoomId(long chatroom_id) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
MsgChatRoom msgChatRoom = new MsgChatRoom();
ft.replace(R.id.activity_chat_MsgChatroom_container, msgChatRoom, "messages");
ft.addToBackStack(null);
ft.commit();
msgChatRoom.startQuery(chatroom_id);
}
I could call the startQuery method, but in that method I need some arguments should be initialize in onCreateActivity(). However, at the time when I call startQuery, the Fragment does not have called OncreateActivity. So there will be a error:
.... on a null object reference
How to solve this problem. Thanks in advance.
You can pass arguments to the fragment by using Fragment's setArguments(Bundle) function.
When you create the fragment pass your arguments by setArguments() and then in your fragment retrieve them by calling getArguments() in this way you don't wait for specific fragment's life-cycle to be able to use your data.
For more information you can visit http://developer.android.com/reference/android/app/Fragment.html which also contains couple of examples of using these functions

How to replace fragment properly using navigation drawer

I am using navigation drawer and it is simple to use. I am not providing the complete code but providing you detail which could be easy for you to understand my problem. I am using fragments these are about 8 in numbers and I am replacing them with one an other. But here comes a problem
I am replacing them on click event of the navigation drawer. but there are two main problems
After replacement , I can see the previous fragment in the background. does replace method just call the new fragment over it ? if yes then what should I do to old fragment not be visible in the background of my new fragment.
When I click navigation drawer Item , it loads the specific fragment successfully. but keeping in that fragment when I click to that specific item again it loads this fragment again and again. For example if drawer item num 3 opens fragment MyBook , then by clicking item num three 2 or many times would open fragment that much time.
So please some one answer me how to cure my app for such kind of actions which I described above.
I tried like this. Its working fine me
FragmentManager frgmanager = getFragmentManager();
frgmanager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction frgTransaction = frgmanager.beginTransaction();
if(subitem.equalsIgnoreCase("subitem")){
Frag1 frg1 =new Frag1(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg1);
}else if(subitem1.equalsIgnoreCase("subitem1")){
Frag2 frg2 =new Frag2(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg2);
}else{
Frag2 frg3 =new Frag3(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg3);
}
frgTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
frgTransaction.commit();
you can use addtobackstack in fragmentstranstion object.like
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.addtoBackStack(null).commit();
Use replace-method of FragmentTransaction instead of add (http://developer.android.com/guide/components/fragments.html#Transactions)
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.commit();
To avoid re-instantiating the fragment, keep track of the current open fragment and only do a fragment transaction, if we next-to-be-opened fragment is a different one than the current.
This may achieved like the following:
class MyActivity ... {
private String currentFragment;
private void openNewFragment(Fragment fragment) {
String newFragment = fragment.getClass().getSimpleName();
if (newFragment.equals(currentFragment)){
// new fragment already shown
return;
}
// Fragment transaction etc here:
}
}
Note that this only compares fragments based in their class name. Sometimes this might not be unique, e.g. if there is a DetailFragment class which displays information about an entity. Which entities details to show may depend on intent arguments.
The above code however will then prevent opening DetailFragment for Entity=1 if currently details for Entity=2 are shown. For these scenarios the information about the fragment kept needs to be extended (e.g. storing a Reference or WeakReference to the fragment instance itself).

Categories

Resources