OnCreateView not called again after replacing with the same fragment - android

I am using a drop-down menu with the different items in the toolbar. In the activity, I am adding the fragment as soon as the menu item is clicked. The fragment OnCreateview gets called and the data is fetched from the API. The logic for the fetching of data remains same for all menu items but only the API endpoint differs. So I am trying to pass the Bundle with API endpoint name and using the same fragment for all the items. But the problem is OnCreateView gets called only first time and the request is made only for first fragment transaction even if I am replacing the same fragment for different item click.
Activity.java
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
switch (i) {
case 0: //Clients
Bundle bundle1 = new Bundle();
bundle1.putString("hash-key","item1");
ReportCategoryFragment rp1 = new ReportCategoryFragment();
rp1.setArguments(bundle1);
replaceFragment(rp1,false,R.id.container);
break;
case 1:
Bundle bundle2 = new Bundle();
bundle2.putString("hash-key","item2");
ReportCategoryFragment rp2 = new ReportCategoryFragment();
rp2.setArguments(bundle2);
replaceFragment(rp2,false,R.id.container);
break;
}
}
ReportCategoryFragment
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_runreport, container, false);
setHasOptionsMenu(true);
ButterKnife.bind(this, rootView);
presenter.attachView(this);
reportType = getArguments().getString("hash-key");
Log.v("hashkey",reportType);
presenter.fetchCategories(reportType, false, true);
return rootView;
}
replaceFragment Function
public void replaceFragment(Fragment fragment, boolean addToBackStack, int containerId) {
invalidateOptionsMenu();
String backStateName = fragment.getClass().getName();
boolean fragmentPopped = getSupportFragmentManager().popBackStackImmediate(backStateName,
0);
if (!fragmentPopped && getSupportFragmentManager().findFragmentByTag(backStateName) ==
null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(containerId, fragment, backStateName);
if (addToBackStack) {
transaction.addToBackStack(backStateName);
}
transaction.commit();
}
}
EDIT: FragmentnewInstance method
public static ReportCategoryFragment newInstance() {
ReportCategoryFragment fragment = new ReportCategoryFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
return fragment;
}

Simple solution is to use Broadcast Receiver
Declare this in your fragment class
BroadcastReceiver broadCastNewMessage = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//extract our message from intent
String msg_for_me = intent.getStringExtra("some_msg");
}
};
Now in onCreate() of fragment register this
registerReceiver(this.broadCastNewMessage, new IntentFilter("update_fragment"));
And in onDestroyView()
unregisterReceiver(broadCastNewMessage);
Now Call this method from the service class where u want to update the activity from your menu selection
Intent intent = new Intent("update_fragment");
intent.putExtra("some_msg", message);
sendBroadcast(intent);

Try using static method in fragment to create new instance of the fragment.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}

Related

How to use Layout inflater without onCreateView

so my code is supposed to support both phone and tablet (tablet with fragments). I know how to inflate the fragment and set the necessary values in the MessageFragment class but I am supposed to do this in the MessageDetails class instead. I don't know how to do that.
ChatWindow class has my code that launches based on if I am on the phone or tablet:
myDisplay.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(isTablet){
MessageFragment mFragment = new MessageFragment();
Bundle bundle = new Bundle();
String idString = String.valueOf(id);
bundle.putString("message_id", idString);
String message = cursor.getString(cursor.getColumnIndex(ChatDatabaseHelper.KEY_MESSAGE));
bundle.putString("message_value", message);
mFragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.frme, mFragment).addToBackStack(null) .commit();
} else { Intent intent = new Intent(ChatWindow.this, MessageDetails.class);
String idString = String.valueOf(id);
String message = cursor.getString(cursor.getColumnIndex(ChatDatabaseHelper.KEY_MESSAGE));
intent.putExtra("message_id", idString);
intent.putExtra("message_value", message);
startActivity(intent); } //for phone
}
});
Here is my onCreateView code for the MessageFragment Class:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup parent, #Nullable Bundle savedInstanceState) {
// Inflate the xml file for the fragment
View rootView = inflater.inflate(R.layout.activity_message_details, parent, false);
return rootView;
}
And Finally, this is my MessageDetails class where I am supposed to inflate the fragment for tablet and assign values (you can see the code for phone layout is already there).
public class MessageDetails extends Activity {
String id;
String message;
MessageFragment mfragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_details);
Bundle bundle;
TextView delMsg;
TextView delId;
Button delBtn;
bundle = getIntent().getExtras();
setId(bundle.getString("message_id"));
setMessage(bundle.getString("message_value"));
//Missing Fragment Inflater code
delMsg = (TextView) findViewById(R.id.delMsg);
delId = (TextView) findViewById(R.id.delId);
delBtn = (Button) findViewById(R.id.delBtn);
delMsg.setText(message);
delId.setText(id);
delBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MessageDetails.this, ChatWindow.class);
intent.putExtra ("delete_id", id);
setResult(RESULT_OK);
startActivityForResult(intent, 33);
finish();
}
}
);
}
public void setId(String delId) {
delId = id;
}
public void setMessage(String delMessage) {
delMessage = message;
}
public String getId() {
return id;
}
public String getMessage() {
return message;
}
}
If you want to embed the fragment based on some business logic, then you can try
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
or, If the fragment is already present in your activity's layout xml file, the fragment will be instantiated whenever the activity's layout is inflated by the system and the onCreateView method of the fragment will be called.
As per the official documentation,
When the system creates this activity layout, it instantiates each fragment specified in the layout and calls the onCreateView() method for each one, to retrieve each fragment's layout. The system inserts the View returned by the fragment directly in place of the element.
Please follow the official documentation from the below link for better understanding the Fragment lifecycle.
https://developer.android.com/guide/components/fragments.html#Creating
Since MessageDetails is an Activity. You can try something like this:
getLayoutInflater().inflate(your_xml_layout)

putExtra from activity then getExtra in fragment

i tried to put and get extra from activity to fragment . but something is wrong! anybody have idea? my case is diffrent because i wanna do it in fragment
myActivity :
if(email.matches(users.user1)&&password.matches(users.pass1)){
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
Intent i = new Intent(LoginActivity.this,ProfileFragment.class);
i.putExtra("pn", users.pn1);
i.putExtra("name", users.name1);
i.putExtra("family", users.family1);
i.putExtra("rank", users.rank1);
startActivity(intent);
finish();
}
myfragment
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_profile2, container, false);
final TextView pn =getActivity().findViewById(R.id.pn);
final TextView name =getActivity().findViewById(R.id.name);
final TextView family =getActivity().findViewById(R.id.family);
final TextView user =getActivity().findViewById(R.id.user);
final TextView rank =getActivity().findViewById(R.id.rank);
String pnget = getActivity().getIntent().getStringExtra("pn");
String nameget = getActivity().getIntent().getStringExtra("name");
String familyget = getActivity().getIntent().getStringExtra("family");
String userget = getActivity().getIntent().getStringExtra("user");
String rankget = getActivity().getIntent().getStringExtra("rank");
pn.setText(pnget);
name.setText(nameget);
family.setText(familyget);
user.setText(userget);
rank.setText(rankget);
}
Hi . i tried to put and get extra from activity to fragment . but something is wrong! anybody have idea?
You start an intent call intent. But the intent have data is i, and it have't started yet.
You can use setArgument and getArgument to send and receive data from activity to fragment or from fragment to fragment:
In YourReceiveFragment:
public static Fragment newInstance(String data1, String data2, ...) {
Fragment f = new YourReceiveFragment();
Bundle bundle = new Bundle();
bundle.putString(DATA_RECEIVE1, data1);
bundle.putString(DATA_RECEIVE2, data2);
f.setArguments(bundle);
return f;
}
In your activity: Just call it:
Fragment f = YourReceiveFragment.newInstance(yourString1, yourString2);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.main_container, f).commit();
Then in YourReceiveFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null){
String dataReceive1 = getArguments().getString(DATA_RECEIVE1);
String dataReceive2 = getArguments().getString(DATA_RECEIVE2);
}
}
In case you want to send data from an activity to a fragment in another activity, use interface or an easier way is just pass the data to the activity which contains fragment and from that, send data to fragment.
You can't create a Fragment with startActivity. You need to create the fragment with bundle like this:
ProfileFragment fragment = new ProfileFragment();
Bundle args = new Bundle();
args.putString("name", users.name1);
args.putString("family", users.family1);
fragment.setArguments(args);
// then tell the FragmentManager to attach the fragment
// to the activity
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.your_placeholder, fragment);
ft.commit();
Then in your onCreateView get them with:
String name = getArguments().getString("name", "");
String family = getArguments().getString("family", "");
Please remember that you need to move the return code to the last of onCreateView method and change your code to something like this:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile2, container, false);
TextView pn =view.findViewById(R.id.pn);
...
return view;
}
You can send data with the bundle, that is recommended
To Pass Data from Activity
fragment = new YourFragment();
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
Bundle bundle = new Bundle();
bundle.putString("key", "value");
fragment.setArguments(bundle);
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
}
To receive data from Fragment
String var = getArguments().getString("value");

Fragment's getArguments() method returns null. Using a ViewPager, passing Arguments through a FragmentPager Adapter

I pass my data as a parcelableArrayList from Activity-->Adapter-->Fragment. In my static newInstance() method, I'm instantiating a Fragment and setting its arguments. I check if the arguments are set or not in the newInstance() method itself. When I try to access the data in my onCreate(), I get a null Pointer Exception.
Adapter where I'm passing the data to fragments:
#Override
public Fragment getItem(int position){
switch(position){
case 0:
return StatusFragment.newInstance("Hahahahah, Dumbfuck");
case 1:
return GraphListFragment.newInstance(position, tempBundle);
case 2:
return GraphListFragment.newInstance(position, humBundle);
case 3:
return GraphListFragment.newInstance(position, pressureBundle);
default:
return GraphFragment.newInstance(1);
}
}
My static newInstance() method:
public static Fragment newInstance(int position, Bundle savedInstanceState){
GraphListFragment graphListFragmentInstance = new GraphListFragment();
if(savedInstanceState != null){
Bundle bundle =new Bundle();
bundle.putParcelableArrayList("list", savedInstanceState.getParcelableArrayList("list"));
graphListFragmentInstance.setArguments(bundle);
Log.d("==============>>>>", graphListFragmentInstance.getArguments().toString());
}
return new GraphListFragment();
}
Here's the Log result:
D/==============>>>>: Bundle[{list=[com.ishanvadwala.cmpe295b.Model.TemperatureData#8da04a0, com.ishanvadwala.cmpe295b.Model.TemperatureData#5fce859, com.ishanvadwala.cmpe295b.Model.TemperatureData#9503c1e, com.ishanvadwala.cmpe295b.Model.TemperatureData#6aeecff, ....
Here's my onCreate() where I'm trying to access the data:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("onCreate====>>>>", getArguments().toString());
/*
List<?> list = (ArrayList<? extends Parcelable>) getArguments().getParcelableArrayList("list");
if(list.get(0) instanceof TemperatureData){
for(TemperatureData tempData: (List<TemperatureData>)list){
System.out.println("I got this: "+tempData.getTemperature());
}
}
*/
}
I've looked at several StackOverflow posts and I still have no idea what I'm doing wrong.
Replace
return new GraphListFragment();
With
return graphListFragmentInstance;
That's the actual Fragment with the Bundle!
Also, creating a new Bundle is useless. Just set the one you are passing
if(savedInstanceState != null){
// Bundle bundle =new Bundle();
// bundle.putParcelableArrayList("list", savedInstanceState.getParcelableArrayList("list"));
graphListFragmentInstance.setArguments(savedInstanceState);
Log.d("==============>>>>", savedInstance.toString());
}
return graphListFragmentInstance;
How to pass args to fragment
SET
Bundle bundle = new Bundle();
bundle.putString("Video1", "Sosis");
bundle.putString("Video2", "Dumb");
Fragment fragment = new YourFragment();
fragment.setArguments(bundle);
// Attach the fragment
GET
public static class YourFragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if (getArguments() != null)
{
Log.e(getArguments().getString("Video1", ""));
Log.e(getArguments().getString("Video2", ""));
}
}
}

Communication between fragment in Navigation Drawer

I am trying to send data from Fragment A to Fragment B of NAVIGATION Drawer on Button click.I tried with bundle and intent but both of them are not working.
In Fragment A I have editText and button when I click the data is passed to another fragment.
In Fragment B there is textView where editText data is going to show but I am not getting a way to communicate between fragment in Navigation Drawer
When lauching Fragment from first fragment
Bundle bundle = new Bundle();
bundle.putString("key", YOUR_EDITVIEW_TEXT);
Fragment fragment = new SECONDFragment();
if (arguments != null) {
fragment.setArguments(arguments);
}
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.container, fragment);
ft.addToBackStack("");
ft.commit();
And in SecondFragment
private String mData;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mData = getArguments().getString("key");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.YourLayout, container, false);
TextView text = (TextView) rootView.findViewById(R.id.yourTextView);
text.setText(mData);
return rootView;
}
Let your Activity to do the communication.
Take a public static variable in your MainActivity from where you're controlling the Fragment replaces of the navigation drawer. When you click the button in FragmentA store the value in the EditText to the public static variable of your MainActivity. Then when FragmentB is loaded check if the public static value is null or not. If not null place the value of that variable to your desired position.
This is not an elegant way for passing values between fragments, but in your case it'll work just fine.
If you're looking for how to pass values from one fragment to another, try something like this.
// To pass some value from FragmentA
FragmentB mFragmentB = new FragmentB();
Bundle args = new Bundle();
args.putString("VALUE", value);
mFragmentB.setArguments(args);
And from your FragmentB use the code to get the values passed.
Bundle args = getArguments();
int value = args.getString("VALUE");
1- create Application Class
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
private static MyApplication mInstance;
public static synchronized MyApplication getInstance() {
return mInstance;
}
String mytext;
public String getMytext() {
return mytext;
}
public void setMytext(String mytext) {
this.mytext = mytext;
}
}
2- app name tag in manifast
<application
android:name=".MyApplication"
.......
3- from first Fragment
MyApplication.getInstance().setMytext("your text here");
4- from other Fragment
String text=MyApplication.getInstance().getMytext();
//Put the value
YourNewFragment ldf = new YourNewFragment ();
Bundle args = new Bundle();
args.putString("KEY", "VALUE");
ldf.setArguments(args);
//Inflate the fragment
getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();
In onCreateView of the new Fragment:
//Retrieve the value
String value = getArguments().getString("KEY");

How to pass changed data back to Fragment's list?

I have a ListFragment with arbitrary data. When I tap on an item, it's data passes through Bundle to another EditFragment, where I retrieve it and store in EditText for editing. How do I pass edited data back and apply changes for the selected item in arraylist? Same way through Bundle? Am I supposed to access ListFragment's listview at the same time?
EditFragment:
public class EditFragment extends Fragment {
MenuItem save;
MenuItem cancel;
View view;
EditText editText;
int position;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
view = inflater.inflate(R.layout.edit_fragment_layout, container, false);
editText = (EditText) view.findViewById(R.id.editText);
Bundle b = getArguments();
position = b.getInt("position");
editText.setText(b.getString("name"));
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.edit_fragment, menu);
save = menu.findItem(R.id.save);
cancel = menu.findItem(R.id.cancel);
cancel.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
MyListFragment myListFragment = (MyListFragment) getFragmentManager().findFragmentByTag("MyListFragment");
fragmentTransaction.replace(R.id.fragContainer, myListFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
return true;
}
});
save.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
MyListFragment myListFragment = (MyListFragment) getFragmentManager().findFragmentByTag("MyListFragment");
//here we need to save changed data in our arraylist
Bundle bundle = new Bundle();
bundle.putInt("position", position);
bundle.putString("name", editText.getText().toString());
myListFragment.setArguments(bundle);
//should I get my bundle data here?
Bundle b = getArguments();
//ArrayAdapter adapter = (ArrayAdapter) myListFragment.getListView().getAdapter();
fragmentTransaction.replace(R.id.fragContainer, myListFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
return true;
}
});
}
}
Upon creation of EditFragment set your invoking ListFragment as EditFragment's target by calling myEditFragment.setTargetFragment(this, 0);.
In your EditFragment, get that fragment object with getTargetFragment() and call onActivityResult method of fragment.
In list fragment override onActivityResult and get bundle from intent to get data.
Hope it helps.

Categories

Resources