I am in the process of making my first app for Android, and I have a Fragment that gets added to my Activity in the Activity's onCreate() method. The problem I am facing is that I am unable to find any of the views contained within the Fragment from the Activity's onCreate() method.
Other threads have suggested that this is because the Fragment has not yet been inflated, so findViewById() will return null for any views contained within the Fragment.
Here is what I mean:
Activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("activity onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
return;
}
initialiseUI(); // Fragment added to Activity
System.out.println("end of activity onCreate");
}
Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
System.out.println("fragment onCreateView");
return inflater.inflate(R.layout.event_log, container, false);
}
This prints the results:
activity onCreate
end of activity onCreate
fragment onCreateView
Because of this order, any attempt to access the views of the Fragment in the Activity's onCreate() method (using findViewById()) produces a NullPointerException, as the Fragment's onCreateView() only gets called AFTER the end of the Activity's onCreate().
Using the FragmentManger's executePendingTransactions() after adding the Fragment doesn't help.
Basically, I have been forced to put the problem code in the Activity's onStart() method instead of onCreate(), as onStart() happens AFTER the Fragment's onCreateView().
Does anyone what the standard practice here is, or how I can make my Fragment-View-accessing code work within the Activity's onCreate() method?
Update your views in onCreateView().
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.event_log, container, false);
TextView tv = (TextView) view.findViewById(R.id.text);
tv.setText("hello world");
return view;
}
Or if your changes depend on Activity your Fragment is attached to, use onActivityCreated().
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView tv = (TextView) getView().findViewById(R.id.text);
tv.setText(getActivity.getSomeText());
}
Related
I could use onCreateView() to get a reference to a a child view in a fragment, and then write a getter method inside the same fragment for this view, which would be called by the Activity to get a reference to the view. Like:
#Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup container, Bundle savedInstanceState) {
LinearLayout rootLinearLayout = (LinearLayout) layoutInflater.inflate(R.layout.my_fragment, container, false);
javaCameraView = (JavaCameraView) rootLinearLayout.findViewById(R.id.myFragment_javaCameraView);//***********
return rootLinearLayout;
}
JavaCameraView getCameraView() {
return javaCameraView;
}
But the problem is that I need the child view inside the Activity's onCreate(), and I think onCreateView() of fragment is called AFTER the onCreate() of Activity returns. Reference
So is there a way to get a reference to a fragment's view, inside the onCreate() of the Activity?
You are doing it wrong. You should not be exposing a fragment's UI elements to the hosting activity. A fragment should encapsulate it's views and functionality. If you are really only using the fragment as a UI component, create a custom View and use that in the activity.
To answer your question, no, you can't get a reference to the fragment's view in the activity's onCreate(). The reason is that the fragment's view doesn't exist until the fragment has gone through it's lifecycle. There's no guarantee when that's going to happen, which is why it's bad to be coding based on such assumptions.
If the fragment needs to communicate events back to the activity, have your activity implement a listener interface, and have the fragment call that interface when appropriate.
So in your case, you could do something like this in the fragment's onCreateView(),
if (getActivity() instanceof Listener) {
((Listener)getActivity()).onViewCreated(fragmentViews);
}
But again, that's doing it wrong.
To call onCreateView() manually should work, though this is not a good way to do it.
private JavaCameraView javaCameraView;
#Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup container, Bundle savedInstanceState) {
LinearLayout rootLinearLayout = (LinearLayout) layoutInflater.inflate(R.layout.my_fragment, container, false);
javaCameraView = (JavaCameraView) rootLinearLayout.findViewById(R.id.myFragment_javaCameraView);
return rootLinearLayout;
}
JavaCameraView getCameraView(LayoutInflater layoutInflater) {
if (javaCameraView == null) {
onCreateView(layoutInflater, null, null);
}
return javaCameraView;
}
You can then use yourFragment.getCameraView(getLayoutInflater()) in your onCreate().
This question already has answers here:
NullPointerException accessing views in onCreate()
(13 answers)
Closed 8 years ago.
EDIT
Changed title.
SDK Guide document says, Activity.onCreate complete after Fragment.onCreateView and Fragment.onAcvityCreated.
But If I try findViewById for a view of the fragment it returns null.
How can I access contents of the fragment?
I'm very new to Android UI dev.
Below is a sample code generated by Eclipse IDE.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
// this is null
View rootView = findViewById(R.id.txtView);
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
First of all, I want to access inner contents of the 'fragment_main'.
Can I do this with findViewById?
I found that calling findViewById for a view of the fragment at onCreate call is not working.
How do I know when the Fragment views are ready at the Activity level?
I read How to implement OnFragmentInteractionListener
Am I needed to manually implement a event listener for this?
I think short answer is 'impossible' or 'not works like that'.
If one want to manage inner contents of fragments just delete fragments and move all the contents to the activity layout.
But If I try findViewById for a view of the fragment it returns null.
You can not just access the view of the fragment in your activity's oncreate or where ever, you can call view of the fragment in your activity.
I found that calling findViewById for a view of the fragment at onCreate call is not working.
That is because the view is not inflated yet in your fragment thus returning null.
Have a look at the fragment life cycle:
(source: xamarin.com)
As you can see onCreate is before onCreateView which you inflate your view for the fragment's layout.
solution:
you call findViewByIdit in your fragment's onActivityCreated.
sample:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView sample = (TextView) getView().findViewById(your_id);
}
I'm attaching the fragment (many fragments to FrameLayout) of an Activity each fragment has its own view inflated in onCreateView().
Now,
If I rotate the screen Landscape/Protrait the onCreateView() of the fragment is called instead of calling its attached Activity's onCreate() method. Because of this the view are rendered twice.
I want the Activity's onCreate() to be called every time when there is a config changes. Is it possible?
Activity : MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
getSupportFragmentManager().beginTransaction()
.add(R.id.layout_replace, new MyFragment()).commit();
}
Fragment : MyFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return (ScrollView)inflater.inflate(R.layout.some_layout, container, false);
}
Fixed this!!
Actual problem was with FragmentTransaction for which I'm adding fragments using .add() which causes the view to be populated twice.
Instead use :
.replace(R.id.yourId, fragment)
I am using several fragments to be dynamically added into activity. Everything works fine, when I press back-button, the fragments go to backstack. And when I resume it, it appears. But everytime on Resume, it is recreating the fragment and call onCreateView. I know it is a normal behavior of the fragment lifecycle.
This is my onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.competitive_programming_exercise, container, false);
return rootView;
}
I want to stop those fragments from recreating. I tried with onSavedInstanstate but nothing is working. How can I accomplish that?
In the Activity's onCreateView set the savedInstanceState to null before calling the super method. You could also remove only the keys "android:viewHierarchyState" and "android:fragments" from the savedInstanceState bundle. Here is code for the simple solution, nulling the state:
#Override
public void onCreate(Bundle savedInstanceState)
{
savedInstanceState = null;
super.onCreate(savedInstanceState);
...
}
Iam using 5 fragments and working for me good as I was facing the same issue before..
public class MyFragmentView1 extends Fragment {
View v;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (v == null)
v = inflater.inflate(R.layout.my_fragment_view_layout,
container, false
);
return v;
}
}
I put the view variable inside class and inflating it as new only if the view instance is null or otherwise use the one created before
You can't stop the fragment from being recreated, unfortunately. The best you can do is to remove the fragment in a transaction, after it has been restored but before it gets displayed.
If you know you are going to remove the fragment immediately you can reduce the performance hit of restoring the fragment by simplifying methods such as onCreateView() to return a dummy view, rather than inflating the whole view hierarchy again.
Unfortunately the tricky part is finding the best place to commit this transaction. According to this article there are not many safe places. Perhaps you can try inside FragmentActivity.onResumeFragments() or possibly Fragment.onResume().
I am using google map v2 in my application, but when I try to create a object for SupportMapFragment with onActivityCreated() this method is not getting called somebody please
help me
Here is my code,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
Log.d("err", "onCreateView");
view = inflater
.inflate(R.layout.todays_deal_location, container, false);
mFragment = new SupportMapFragment() {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("err", "onActivityCreated");
GoogleMap map = mFragment.getMap();
}
};
return view;
}
You should know the lifecycle of the Fragments and also the purpose the onCreateView() and onActivityCreated() methods in `Fragments.
onCreateView():
Here we inflate the layout or simply create the view and further if you have to do anything that takes reference to Activity don’t do it like creating dialogs,accessing views of Activity etc because,this place doesn’t ensure that hosting Activity is fully functional
onActivityCreated():
This method place signifies that our hosting Activity views are created and hosting Activity is functional and this is the right place to do all your Activity related task.
onActivityCreated() Called when the fragment's activity has been created and this fragment's view hierarchy instantiated. It can be used to do final initialization once these pieces are in place, such as retrieving views or restoring state. It is also useful for fragments that use setRetainInstance(boolean) to retain their instance, as this callback tells the fragment when it is fully associated with the new activity instance. This is called after onCreateView(LayoutInflater, ViewGroup, Bundle) and before onStart().
This is how to add SupportMapFragment to your fragment correctly:
http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1
Note:
R.layout.layout_with_map doesn't contain fragment
using getChildFragmentManager()