Android Fragment Null pointer exception - android

I am learning android developing(novice).I want to add a fragment to the mainActivity with a textview and change the text. This code works perfectly:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
((TextView)view.findViewById(R.id.textview)).setText("some text");
return view;
}
}
But this codes invokes null pointer exception:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
return view;
}
public void updateText() {
textt.setText("some text");
}
}
and:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
View view;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_fragment1, container, false);
return view;
}
public void updateText() {
((TextView)view.findViewById(R.id.textview)).setText("some text");
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment1 frg1 = new Fragment1();
ft.replace(R.id.fragment_container, frg1);
ft.addToBackStack(null);
ft.commit();
frg1.updateText();
}
}
why these codes providing different outcome?
my project

frg1.updateText(); is called before the onCreateView lifecycle method of your fragment is called.. You should call the method after you set
textt = (TextView)view.findViewById(R.id.textview);
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
this.updateText();//here
return view;
Check out fragment lifecycle docs regarding onCreateView
The system calls this when it's time for the fragment to draw its user interface for the first time.
This will happen when fragment is loaded not when it is created in your activity.

Here, the textview is not created when you call the updateText function.
Do such calls inside your fragment. Not on the activity which houses the fragment.

Related

Can't change fragment text view from a method

I'm trying this simple method to change a fragment text view but the app crashes every time I try to open the activity of the fragment with this fragment code
public class FragmentContrat extends Fragment {
public FragmentContrat() {}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.contrat_fragment, container, false);
update();
return view;
}
public void update() {
TextView textView = (TextView)getView().findViewById(R.id.souscripteur_txt);
textView.setText("milan");
}
however it works fine and the TextView change when I put the same code in onCreateView like this :
public class FragmentContrat extends Fragment {
public FragmentContrat() {}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.contrat_fragment, container, false);
TextView textView = (TextView)view.findViewById(R.id.souscripteur_txt);
textView.setText("milan");
return view;
}
the activity code :
public class DetailsContrat extends AppCompatActivity {
TabLayout details_tab;
AppBarLayout details_bar;
ViewPager details_pager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details_contrat);
Intent i = getIntent();
String client_id = i.getStringExtra("client_id");
details_tab=(TabLayout)findViewById(R.id.details_tab);
details_bar=(AppBarLayout) findViewById(R.id.details_bar);
details_pager=(ViewPager)findViewById(R.id.details_pager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
FragmentContrat fragmentContrat = new FragmentContrat();
FragmentVehicule fragmentVehicule = new FragmentVehicule();
FragmentGaranties fragmentGaranties = new FragmentGaranties();
adapter.AddFragment(fragmentContrat,"MON CONTRAT");
adapter.AddFragment(fragmentVehicule,"MA VOITURE");
adapter.AddFragment(fragmentGaranties,"MES GARANTIES");
details_pager.setAdapter(adapter);
details_tab.setupWithViewPager(details_pager);
}
}
In onCreateView you are creating and the fragment's view. So if you call getView(), to get the fragment view you will get null, because you haven't yet returned the just created view.
You can:
Use the newly-created view similarly to what #Sanjaysinh's is recommending
Avoid setting your text in onCreateView and set it in onViewCreated(View view, Bundle savedInstanceState), that is called after the view has been created (docs)
I think you need to pass your view in update method
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.contrat_fragment, container, false);
update(view);
return view;
}
public void update(View view) {
TextView textView = (TextView)view.findViewById(R.id.souscripteur_txt);
textView.setText("milan");
}

which method when display dialog show in fragment

I opened dialog in a fragment and when come back to fragment, my fragment's view is null Object.
when the dialog is displaying which lifecycle method fragment is calling?
public class MyFragment extends Fragment{
TextView textView;
View view;
FloatingActionButton actionButton;
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_read, container, false);
textView = view.findViewById(R.id.txtSaved);
actionButton = view.findViewById(R.id.floatingActionButton);
actionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DialogSearch search = new DialogSearch();
search.show(getActivity().getSupportFragmentManager(),"MyDialog");
}
});
return view;
}
}
The problem is the dialog is being showned in the onCreateView life cycle, that is why is the Fragment view is null. You have to do it inside the onViewCreated method.
#Override
public View onViewCreated(View view, Bundle savedInstanceState) {
//Work here, the view argument in the method is the view inflated in the onCreateView method
});
Make a small change,
public class MyFragment extends Fragment{
TextView textView;
View view;
FloatingActionButton actionButton;
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_read, container, false);
textView = view.findViewById(R.id.txtSaved);
actionButton = view.findViewById(R.id.floatingActionButton);
actionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DialogSearch search = new DialogSearch();
search.show(getActivity().getSupportFragmentManager(),"MyDialog");
}
});
return view; / Add this line -------
}
}
You need to return view
when the dialog is displaying which lifecycle method fragment is calling?
onPause() of fragment gets called.

How to use shared element transition between FirstFragment (including RecyclerView) and SecondFragment

I could implement shared element transition between two fragments WITHOUT RECYCLERVIEW!!!
This is FirstFragment:
public class FirstFragment extends Fragment {
ImageView img_small;
LinearLayout layout_ofc_cities;
LinearLayout layout;
public FirstFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
img_small = (ImageView) view.findViewById(R.id.img_small);
layout_ofc_cities = (LinearLayout) view.findViewById(R.id.layout_ofc_cities);
layout = (LinearLayout) view.findViewById(R.id.layout);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
SecondFragment secondFragment = new SecondFragment();
secondFragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
secondFragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
FragmentTransaction ft = getFragmentManager().beginTransaction()
.replace(R.id.container, secondFragment)
.addToBackStack(null)
.addSharedElement(layout_ofc_cities, "transitionTxt")
.addSharedElement(img_small, "transitionImg");
ft.commit();
}
}
});
return view;
}
}
and this is SecondFragment:
public class SecondFragment extends Fragment {
public SecondFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
return view;
}
}
And it works!
but when I implements a RecyclerView in FirstFragment to use SharedElementTransition for a LinearLayout and an ImageView of RecyclerView to a LinearLayout and an ImageView in SecondFragment it doesn't work.
I want a sample code with two Fragments that the first one has RecyclerView in it, with animation between their shared elements. Can anyone help me?
I found the answer:
the solution is on this page:
http://jemsdevmobile.com/2016/02/11/lollipop-transition-between-activities/
just you need to change xml tags. for example change "imageview" to "ImageView"

What is the meaning of re-inflating view in fragment?

While adding user interface to a fragment it is shown to inflate the view each an every call to onCreateView:
public static class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
reference: http://developer.android.com/guide/components/fragments.html#UI
What if I cache the view inflated and return it on next calls such as:
public static class ExampleFragment extends Fragment {
private View mView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(mView == null){
mView = inflater.inflate(R.layout.example_fragment, container, false);
}else{
//detach mView from previous parent if exist
...
}
return mView;
}
}
Fragment manager already handles such optimizations for you.
onCreateView() is only called when the fragment view needs to be created. When it's already created in a usable state, onCreateView() won't be called.

extends Activity with Fragment in Android

I am using Fragment for Sliding Menu. Now, I want to extend Activity to get reference of layout.xml and many more. But we can't bind Fragment and Activity together. So what is the way to solve this ?
Fragment Code :
public class FindPeopleFragment extends Fragment {
public FindPeopleFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.becomeexpert, container,
false);
return rootView;
}
}
If I am using extends Fragment then I can't use findViewbyId and many more things. So I am confused as I am using Fragment first time. Please help me regarding this.
Since you have the view inflated you can call rootView.findViewById(...)
I think this is what you are after:
public class FindPeopleFragment extends Fragment {
private View rootView;
private View myTextView;
public FindPeopleFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.becomeexpert, container,
false);
myTextView = rootView.findViewById(R.id.my_textview);
return rootView;
}
private void someFunction()
{
View myButton = rootView.findViewById(R.id.my_button);
}
}
You can save a reference to the views that you need before onCreateView returns, or you can save a reference to the rootView and call findViewById on that later on if you need to.

Categories

Resources