Whenever I use findViewById in my Activity's onCreate I get a NullPointerException. For example:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
TextView mTextView = (TextView) findViewById(R.id.textview);
}
I have read that the problem might by that the views may not be fully loaded when I try to find them and that is why I get a null pointer. If I call for findViewById in onCreateView of my Activity's fragment, everything works fine:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView mTextView = (TextView) rootView.findViewById(R.id.textview);
}
However, I need to use mTextView outside this fragment class. I have seen many examples in Android's official documentation where findViewById is used in the Activity's onCreate. What am I doing wrong?
From the layout xmls, place your textview in the layout xml- activity_main so the activity's setContentView can find it there.
Currently the textview is in the layout xml fragment_main
fyi: fragment_main and activity_main are two different layouts. If your app structure doesn't demand the fragment then you don't need it at all.
you can try something like this -
class MainActivity extends Activity{
public TextView tv;
protected void onCreate(Bundle savedInstance){
......
}
public void doActionOnTextView()
{
//at this point you have the textview in tv
// do what you want to do with it
}
}
class MyFragment extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView mTextView = (TextView) rootView.findViewById(R.id.textview);
mTextView.postRunnable(new Runnable(){
((MainActivity)getActivity()).tv=mTextView;
((MainActivity)getActivity()).doActionOnTextView();
}
}
Its not the best solution, but would work for you now.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
i have started to learn android recently and i was looking at a fragment example in a video tutorial
in the tutorial they haven't made the textview static but when i tried to implement fragment with some changes in the code i started to get null pointer exception my code looks like this
public class BlankFragment2 extends Fragment {
TextView tv;
public BlankFragment2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank_fragment2, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
tv= (TextView) getActivity().findViewById(R.id.txt2);
}
public void setName(String name){
//tv=(TextView)getActivity().findViewById(R.id.txt2);
if(tv == null){
System.out.println("tv is null");
}
tv.setText("Hi "+name);
}
}
i am getting null pointer exception at settext unless i make the textview static can someone please explain why
this is not duplicate of what is NPE i know what NPE is and why it shows up my question here is that after initializing the textview in onActivityCreated why it is null again in setname function
Not getActivity().findViewById(), it must be view.findViewById() because Activity.findViewById() will look for a View in the Activity layout, whereas view.findViewById() will look for the View in the Fragment layout.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflatedView = inflater.inflate(R.layout.fragment_blank_fragment2, container, false);
return inflatedView;
}
And in onViewCreated you can initialise your TextView
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// here goes your intialisation using view
tv= (TextView) view.findViewById(R.id.txt2);
}
Make sure you have a TextView with the id txt2 in fragment_blank_fragment2.xml
NullPointerException is thrown when an application attempts to use an
object reference that has the null value.
FYI
You should return VIEW's object
Check findViewById(R.id.txt2 . Make sure you this ID present in XML.
Don't
tv= (TextView) getActivity().findViewById(R.id.txt2);
Do
tv= (TextView) view.findViewById(R.id.txt2);
Try this way
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_blank_fragment2, container, false);
tv= (TextView) view.findViewById(R.id.txt2);
return view;
}
Sorry guys it was a stupid mistake on my side,
in my mainactivity i wrote
BlankFragment2 frag2 = new BlankFragment2();
frag2.setName(name);
i corrected it by writing
BlankFragment2 frag2=(BlankFragment2)getFragmentManager().findFragmentById(R.id.frag2);
fragb.setName(name);
now it is working
I'm curious about where setText() actually works. Here is a sample code for my question. I skipped irrelevant code with "..." ellipse.
// fragment_main.xml
<RelativeLayout ... >
<TextView
android:id="#+id/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:onClick="userMethod" />
</RelativeLayout>
and
// ActivityMain.java
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.hello_world);
textView.setText("This cause runtime error!!");
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
} // if
} // onCreate
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// gives a compile error about non-static finViewById here
// TextView textView = (TextView) findViewById(R.id.hello_world);
// textView.setText("Compiling Error!!");
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
} // onCreateView
} // PlaceholderFragment
// user defined method
public void userMethod(View view) {
TextView textView = (TextView) findViewById(R.id.hello_world);
textView.setText("This run successful");
} // userMethod
} // class MainActivity
Here is what I don't understand:
textView.setText("string") fail when in protected void onCreate(...)
but
textView.setText("string") run when in public void userMethod(...)
yet
both these methods are in public class MainActivity extends ActionBarActivity
What is the difference??
TextView apparently is in fragment layout. You are trying to reach the textview before you inflate the fragment that's why you get null pointer exception.
Try to settext inside fragment onCreateView() method or after fragment inflate.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// we inflate the fragment here.
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
// get the textview from inflated layout.
TextView textView = (TextView) rootView.findViewById(R.id.hello_world);
textView.setText("Should work");
return rootView;
}
Actually TextView is in your fragment_main.xml and You are calling setText before adding the fragment to the mainActivity and it will make a NullpointerException because of there is no textview in your activity_main.xml.
Here's the code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String message = "Email: \n" +intent.getStringExtra(MainActivity.ACCOUNT_EMAIL);
setContentView(R.layout.activity_display_message);
TextView textView = (TextView) findViewById(R.id.display_info);
//textView.setText(message);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
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_display_message,
container, false);
return rootView;
}
}
The ID name in the XML is definitely right, but for whatever reason this commented line always returns null. When I have the line commented the fragment opens with the text view there (i have some placeholder text). I can't access this thing from the code.
You say that the fragment displays with the TextView, but you're attempting to reference the TextView from your Activity (and the Activity's layout).
Without seeing the layouts, I'm guessing the TextView is in fragment_display_message.xml (and not activity_display_message.xml).
It seems that you want to move the logic of accessing the TextView into your Fragment's onCreateView(). Bear in mind that you may want to use Fragment arguments to set the message as obtaining it directly from the Activity's intent will no longer work.
I am a beginner in coding for Android and i am trying to do an application with two fragments. Unfortunately, when i add code to set action to my layout, it makes my application crash, so i'm wondering where i should put my code on the fragment file. If i take out the function onCreate, the application doesn't crash and my layout is good.
Here is my code. Thank you so much for your answer.
public class FragmentOne extends Fragment{
public static final String TAG = "FragmentOne";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = View.inflate(getActivity(), R.layout.fragmentone, null);
return v;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final EditText etData = (EditText) getView().findViewById(R.id.etData);
}
}
First of all I can see a few mistakes in your code.First of all as #user1873880 mentioned, onCreate() is always called before onCreateView(), so you should consider dealing with your views in onCreateView(). Second mistake which I can see is that you are not creating your View as it's designed to be used on Fragment. In my opinion the way your Fragment should look is like this :
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentOne";
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// create your view using LayoutInflater
return inflater.inflate(R.layout.fragmentone, container, false);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// do your variables initialisations here except Views!!!
}
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
// initialise your views
EditText etData = (EditText) view.findViewById(R.id.etData);
}
}
Hope this helps you! : )
The reason is that onCreate is invoked before onCreateView, so you can manipulate with your views only after onCreateView callback. For more information check Fragment lifecycle here.
In PageFragment; I inflate a layout in onCreateView. But I want to inflate this layout before onCreateView loads. It could be inflated one time / or for every fragment; not important.
How can I achieve it ?
public class PageFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.page_quiz, container, false);
tv = (TextView) view.findViewById(R.id.Text);
LinearLayout ll = (LinearLayout) view.findViewById(R.id.questionList);
return view;
}
}
You just have to provide a layout as the return parameter in onCreateView(), that does not means you have to inflate it there. Layout can come from anywhere. You can Inflate the layout in onAttach() or in onCreate().
use getActivity() to get a LayoutInflater instance:
View layout = LayoutInflater.from(getActivity()).inflate(........);