I have an Activity and a simple fragment ,I try to use Bundle to pass data to the fragment, but the bundle is always null.
I can't figure out what is the problem?!
this is my Activity class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fragmentA =new FragmentA();
Bundle bundle=new Bundle();
bundle.putString("name","Ahmed Ezzat");
fragmentA.setArguments(bundle);
}
public void showFragment(View view) {
FragmentA fragmentA=new FragmentA();
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.dumper,fragmentA,"fragment A");
transaction.commit();
}
}
and this is my fragment class
public class FragmentA extends Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_a,container,false);
textView= (TextView) view.findViewById(R.id.tv_fragment);
Bundle bundle = this.getArguments();
String name = bundle.getString("name");
if (name!=null){
textView.setText(name);}
return view;
}
}
any help?
You never called setArguments in the showFragment method.
The Fragment in the onCreate method is never used.
You may try using the following code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showFragment(View view) {
FragmentA fragmentA=new FragmentA();
Bundle bundle=new Bundle();
bundle.putString("name","Ahmed Ezzat");
fragmentA.setArguments(bundle);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.dumper,fragmentA,"fragment A")
.commit();
}
}
You can pass data to the fragment when building the fragment, then passing it to the transaction.
public class FragmentA extends Fragment {
TextView textView;
String message;
public FragmentA(String message){
this.message = message;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_a,container,false);
textView= (TextView) view.findViewById(R.id.tv_fragment);
textView.setText(message);
return view;
}
And when attaching, you just pass it in the constructor.
Related
HomeFragment.java:
public class HomeFragment extends Fragment {
FirebaseAuth fAuth;
String userId;
Button logout;
FirebaseFirestore fStore;
EditText name,no,mail;
public HomeFragment() {
}
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return 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.fragment_home, container, false);
name=(EditText)view.findViewById(R.id.fname);
mail=(EditText)view.findViewById(R.id.emailid);
no=(EditText)view.findViewById(R.id.phone);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
I have my xml file(fragment_home.xml) which contains three TextView's which Iam unable to modify and my app crashes when trying to do so. I need to set my textview with the data from the firebase.
Please help me find a solution
When passing arguments from the activity to the fragment, the arguments are lost.
Activity:
public class DatePickerFragmentActivity extends AppCompatActivity {
private static final String EXTRA_CRIME_DATE = "CRIME_DATE";
private Date mCrimeDate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
mCrimeDate = (Date) getIntent().getSerializableExtra(EXTRA_CRIME_DATE);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}
private Fragment createFragment(){
return DatePickerFragment.newInstance(mCrimeDate);
}
}
At this point, the fragment still has data in the bundle, checked by debugger.
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
Fragment:
public class DatePickerFragment extends DialogFragment {
private static final String ARG_DATE = "date";
public static DatePickerFragment newInstance(Date date) {
Bundle args = new Bundle();
args.putSerializable(ARG_DATE, date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDate = (Date) getArguments().getSerializable(ARG_DATE);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog_date, container, false);
}
}
But in this place the bundle is already empty:
mDate = (Date) getArguments().getSerializable(ARG_DATE);
The layout of my application looks like this:
ListView Activity/Fragment -> ViewPager Activity/Fragment -> DatePicker Activity/Fragment
Activity A
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ActivityA);
Bundle b = new Bundle();
b.putString("mobile", "123456789");
FragmentA fragmentA = new FragmentA ();
fragmentA .setArguments(b);}
FragmentA
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fragmentA, container, false);
String txtMobile = getArguments().getString("mobile");
Log.i("mobile2",txtMobile);
mobile.setText(txtMobile);}
I have tried above solution but showing error that
Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
May be It's about the way you are adding fragment to the class:
Bundle b = new Bundle();
b.putString("mobile", "123456789");
FragmentA fragmentA = new FragmentA ();
fragmentA .setArguments(b);
fm.beginTransaction()
.replace(placeholder, new FragmentA(), tabId)
.commit();
can you provide more data about how did you add it ?
Create your fragment like this
public static MyFragment newInstance(String string) {
Bundle args = new Bundle();
args.putString("string",string);
MyFragment fragment = new MyFragment();
fragment.setArguments(args);
return fragment;
}
And then in Fragment onCreate use getArguments() for pulling that String. Don't forget to check getArguments() for null.
Try to fetch the argument in onCreate method of fragment with default value constructor:
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String txtMobile = getArguments().getString("mobile", "");
}
and make sure you commit the fragment transaction after settting the arguments in fragment. :)
First check that your argument is not null.
For example
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fragmentA, container, false);
if(getArguments()!=null){
String txtMobile = getArguments().getString("mobile");
Log.i("mobile2",txtMobile);
mobile.setText(txtMobile);
}
}
try this:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null){
String txtMobile = savedInstanceState.getString("mobile");
}
}
you can use inteface to pass data from activity to fragment
In your activity
public interface FragmentRefreshListener {
void onRefresh(String mydata);
}
public FragmentRefreshListener fragmentRefreshListener;
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
Then inside your fragment add below code
((MainActivity) getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh(String mydata) {
// write your logic here
}
});
use following in your activity to pass data from activity to fragment
getFragmentRefreshListener().onRefresh("dummy text");
In my MainActivity there is a FrameLayout (id=fragment_container) that is replaced by the Activity in onCreate with FragmentA. FragmentA just contains a single Button and calls onClick in the MainActivity in order to replace the FrameLayout with FragmentB. FragmentB contains a RecyclerView and is shown correctly. I call fragmentManager.popBackStack() to bring back FragmentA. Now FragmentA is shown on top of FragmentB (which I still can interact with).
Why is FragmentB not removed after calling popBackStack?
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private FragmentManager fragmentManager;
#Override
public void onBackPressed() {
fragmentManager.popBackStack();
}
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, new FragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//...
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentA fragment = FragmentA.getInstance(this); //register OnClickListener
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
//...
}
FragmentA
public class FragmentA extends Fragment {
private View.OnClickListener onClickListener;
public FragmentA() {
}
#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.fragment_a, container, false);
FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
fab.setOnClickListener(onClickListener);
return view;
}
public static FragmentA getInstance(View.OnClickListener onClickListener) {
FragmentA fragmentA = new FragmentA();
fragmentA.setOnClickListener(onClickListener);
return fragmentA;
}
private void setOnClickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
}
FragmentB
public class FragmentB extends Fragment {
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.FragmentB, container, true);
//manipulating Views...
//...
return view;
}
}
The problem is in the FragmentB class. You should not pass the argument attachToRoot=true.
Try this instead:
public class FragmentB extends Fragment {
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//don't pass true
View view = inflater.inflate(R.layout.FragmentB, container, false);
//manipulating Views...
//...
return view;
}
}
Use popBackStackImmediate instead,
#Override
public void onBackPressed() {
fragmentManager.popBackStackImmediate();
}
From the popBackStackImmediate docs,
Like popBackStack(), but performs the operation immediately inside of the call. This is like calling executePendingTransactions() afterwards.
I am developing an Android application. I have a requirement like there is a button in fragment 1, when a user clicks that button result should be displayed in fragment 2. While loading the activity both fragments is attached. Here is my try:
In main activity:
public void dsp(String str) {
secondfragment f2=new secondfragment();
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
f2.setArguments(bundle);
}
In first fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragone, container,false);
Button btn = (Button) v.findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
m.dsp("clicked");
}
});
return v;
}
In second fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragtwo, container,false);
tv= (TextView) v.findViewById(R.id.textView1);
tv.setText(this.getArguments().getString("name"));
return v;
}
When communicating from Fragment to Fragment you use an interface to pass data to the Activity which in turn updates the fragment you want to change.
For Example:
In Fragment 1:
public class FragmentOne extends Fragment{
public Callback mCallback;
public interface Callback{
void onUpdateFragmentTwo(String message);
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
mCallback = (Callback) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragone, container,false);
Button btn = (Button) v.findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mCallback.onUpdateFragmentTwo("clicked");
}
});
return v;
}
}
then in main Activity implement the interface:
public class MainActivity extends AppCompatActivity implements Callback{
FragmentTwo fragmentTwo;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ... Load views or perform logic
// ... Load Fragment Two into your container
if(savedInstanceState == null){
fragmentTwo = FragmentTwo.newInstance(new Bundle()); // use real bundle here
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_holder, fragmentTwo, "Frag2").commit();
}
}
// Interface method
#Override
public void onUpdateFragmentTwo(String message){
// Call activity method with the argument
if(fragmentTwo != null){
fragmentTwo.updateFragmentTwo(message);
}
}
}
Update
In your second fragment I typically use a static newInstance(Bundle args) method to initialize and then would use a public method to communicate from the Activity to the Fragment for example:
public class FragmentTwo extends Fragment{
public static FragmentTwo newInstance(Bundle args){
FragmentTwo fragment = new FragmentTwo();
fragment.setArguments(args);
return fragment;
}
//... Class overrides here onCreateView etc..
// declare this method
public void updateFragmentTwo(String updateText){
// .. do something with update text
}
}
Thats it, happy coding!
Here you have what the Android Documentation says about Communicating Between Fragments. Here you'll have all the necessary steps to make two or more fragments communicate securely :)