I am new in Fragment and I am trying use Activity method in Fragment class. So please help me how I use Activity method in Fragment. And also how I use List<NameValuePair>, SharedPreferences in Fragment.
public class DashboardFragment extends Fragment {
public DashboardFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dashboard, container, false);
return rootView;
}
This is Fragment code and I want to use Activity method in this. So please help I am new in this section. If there is another method, please tell me.
After the fragment's onAttach method is called (see Fragment lifecycle), you can obtain a reference to the activity through fragment's getActivity() method. Then you can cast this reference to the type of your activity and call the method:
((MyActivity)getActivity()).method();
Your activity method needs to be static and public. Then you could do following in your Fragment:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof MyActivity) {
this.activity = activity;
sharedPreferences = activity.getSharedPreferences(...);
}
}
Declare MyActivity activity in your Fragment.
then you can call activity.yourMethod() in another place. Dont forget to check if activity is null.
Use an interface implementation for this. Somethings like this:
Activity:
MyActivity extends AppCompatActivity implements CallBack {
#Override
public void onCallBack() {
// do something
}
}
And Fragment:
MyFragment extends Fragment {
public interface CallBack {
void onCallBack();
}
private CallBack callBack;
#Override
public void onAttach(Activity context) {
callBack = (CallBack) activity;
}
// when clicking or whatever it takes to call
callBack.onCallBack();
}
1) You can get Activity instance with getActivity() method in Fragment:
Activity activity = getActivity();
Then you can call any Activity method with the instance:
activity.method();
2) About SharedPreferences, you can also get Context instance with getContext() method in Fragment.
Context context = getContext();
So you can call getSharedPreferences() method with the instance:
SharedPreferences sharedPreferences = context.getSharedPreferences(String name, int mode);
3) List<T> is a pure Java class. So you can use it in Fragment without any limitation.
Related
I in my app i have a fragment that contains some input fields, i show this fragment in two different activities, in both cases, the layout will be the same but I need to perform different actions based on who is the parent activity.
I'll try to explain better my problem and the solution that I'm using with the following code:
ActivityA
public class ActivityA extends AppCompatActivity{
private NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ActivityA);
navController = Navigation.findNavController(this,R.id.graphA);
initView();
}
public void nextFragment(int actionID, Bundle bundle) {
btn.setOnClickListener(v->{
navController.navigate(from_activityA_toFragment, bundle);
});
}
ActivityB
public class ActivityB extends AppCompatActivity{
private NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ActivityA);
navController = Navigation.findNavController(this,R.id.graphB);
initView();
}
public void nextFragment(int actionID, Bundle bundle) {
btn.setOnClickListener(v->{
navController.navigate(from_activityB_toFragment, bundle);
});
}
In my fragment class now i have something like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.fragemnt, container, false);
if(getActivity().getClass().equals(ActivityA.class))
//Do things of activityA
else if(getActivity().getClass().equals(ActivityB.class)))
//Do things of activityB
return rootview;
}
Now this code work but doesn't seem the best way to archive my goal so have anyone some suggestion? Thanks
You can check the instance
In Java you can use instaceof
if(getActivity() instanceof ActivityA){
// Do things of activityA
}else if(getActivity() instanceof ActivityB){
// Do things of activityB
}
and for Kotlin
if(getActivity() is ActivityA){
// Do things of activityA
}else if(getActivity() is ActivityB){
// Do things of activityB
}
The correct way to do it is to define an interface in the Fragment, make the Activity implement the interface, and make the Fragment cast the Activity to the interface.
The following guide describes it: https://web.archive.org/web/20180405192526/https://developer.android.com/training/basics/fragments/communicating.html
public class HeadlinesFragment extends Fragment {
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
I have two fragment Parent and child, And Now I am trying to get some value from childFragment to parentFragment using callback.
Here is what i have tried so far:
Adding childfragment
activity.getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, fragment).addToBackStack(null)
.commit();
Now on buttonClick of childFragment i want to get response to parentFragment.
Example:
nearestCenter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getFragmentManager() != null) {
getFragmentManager().popBackStack();
}
}
});
P.S
I know how to do with Activity to Fragment but is there any way to get callback from fragment to frag.
You can use below code. Of course you should be careful about class cast exception and null pointer exception.
private void callParentFragmentMethod(){
ParentFragment f = (ParentFragment) getParentFragment();
f.someMethod();
}
You can use interface to interact like this :
public interface MyInterface{
void sendMessageToParent(Parameters parameter);
}
Now implement this on your parent fragment like this -
public class ParentFragment implements MyInterface{
public static Myinterface myinterface;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// Register your interface like this.
myinterface = this;
return view;
}
#Override
public void sendMessage(Parameters Parameters){
}
}
Now from child activity call it like this:-
if(ParentFragment.myinterface!=null){
ParentFragment.myinterface.sendMessageToParent(parameters);
}
This will do. And make sure in onDestroy of parent you assign it null like this:-
myinterface = null;
Hope this helps.
I have this issue of sending some data back and forth between a fragment and its container activity, I succeeded in doing it. What puzzles me is sending my data from the fragment to the activity, at first I implemented OnResume(), OnStop() and sent the data through an intent and that created an infinite loop so I removed them. Then I did setRetainInstance(true) and it worked and gave me the wanted behavior.
My Question is How my data are really being sent and where in the fragment lifecycle ?
The Right approach is to use Interfaces. Don't use onStop or setRetainInstance()
See this. It will solve you problem.
Pass data from fragment to actvity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~
I have a main activity class, and a private inner class within the main activity. The private inner class has methods that when called will display fragments. This inner class implements an interface defined in the Fragment's class, to be used as a sort of callback. It is probably easiest to show through code.
public class MainActivity extends FragmentActivity {
//on a button clicked
EditItemManger em = new EditItemManager();
em.begin();
private class EditItemManager implements on EditItemFragment.EditedItemClickedListener{
//consructor, other stuff. no onCreate method because this inner class does not (explicity??) extend activty
public void begin(){
EditItemFragment editItemFrag = new EditItemFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(editItemFrag, EDIT_FRAG_TAG)
fragmentTransaction.commit();
}
#Override
public void onEditItemClicked() {
editFinish();
}
public void editFinish()
{
// other stuff
}
}
}
My EditItemFragment class, where the onAttach method always has a null activity parameter
public class EditItemFragment extends DialogFragment {
protected EditedItemClickedListener editedItemClickedListener;
protected ImageButton button;
public EditItemFragment(){}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_name_fragment, container, false);
button = (ImageButton) view.findViewById(R.id.submit_new_item_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
editedItemClickedListener.onEditedItemButtonClicked();
}
});
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
editedItemClickedListener= (EditedItemClickedListener) activity;
} catch (ClassCastException e) {
e.printStackTrace();
}
}
public interface OnEditNameButtonClickedListener {
public void onEditNameButtonClicked();
}
So because the parameter in onAttach() in my Fragment class is always null, it eventually causes a null pointer exception. I am wondering if it is because the fragment is called from a class that is not extending activity. The problem is that if this class extends activity, there will be an issue with trying to commit the Fragment Transaction
I guest your onAttach returns nullpointer exception. Its because your parent Activity the main activity doesnt implement your custom interface so it return null. See the code below let me know if it help you:
public class MainActivity extends FragmentActivity implements EditItemFragment.EditedItemClickedListener{
private DialogFragment editItemDialog;
//Do your code here
#Override
public void onEditItemClicked() {
editFinish();
}
public void showDialog(){
//this is for showing your custom dialog fragment
editItemDialog = EditItemFragment.newInstance();
editItemDialog.show(getSupportFragmentManager(),"editItemDialog");
}
}
this is for your EditItemFragment:
public class EditItemFragment extends DialogFragment{
//Do your code here
public static EditItemFragment newInstance(){
EditItemFragment editItemDialog = new EditItemFragment();
return editItemDialog;
}
}
I'm trying to update an object from a fragment contained within a swipe view. The code I have is taken directly from the Android documentation. What I want to do is pass an object from the main CollectionDemoActivity down into the DemoObjectFragment fragment, update it using a button in that fragment and then pass it back up to the main activity. What's the best way to accomplish this?
I've tried passing the object in a bundle as a serialisable through the DemoCollectionPagerAdapter and then again down to the fragment but this seems really cumbersome. I've also tried declaring the object in the main activity and just referencing it in the fragment class but I get complaints that it can't have a non-static reference in a static context.
public class CollectionDemoActivity extends FragmentActivity {
// When requested, this adapter returns a DemoObjectFragment,
// representing an object in the collection.
DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collection_demo);
// ViewPager and its adapters use support library
// fragments, so use getSupportFragmentManager.
mDemoCollectionPagerAdapter =
new DemoCollectionPagerAdapter(
getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mDemoCollectionPagerAdapter);
}
}
// Since this is an object collection, use a FragmentStatePagerAdapter,
// and NOT a FragmentPagerAdapter.
public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
// Our object is just an integer :-P
args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 100;
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
// Instances of this class are fragments representing a single
// object in our collection.
public static class DemoObjectFragment extends Fragment {
public static final String ARG_OBJECT = "object";
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.
View rootView = inflater.inflate(
R.layout.fragment_collection_object, container, false);
Bundle args = getArguments();
((TextView) rootView.findViewById(android.R.id.text1)).setText(
Integer.toString(args.getInt(ARG_OBJECT)));
return rootView;
}
}
So after a lot of searching and reading I found a nice solution that works for me. For those interested I created an interface in the fragment class that is implemented in the Main activity. The methods were kicked off through a button press in the fragment class. This way I was able to pass variables up to the main class without ever needing to pass the entire object down to the fragment.
So my classes were mostly the same with these bits added:
And the fragment class which contains the interface. The onAttach() method needs to be called which gets a reference to the activity that the fragment will be attached to. This activity reference is binded to an instance of the interface in the fragment.
public class DemoObjectFragment extends Fragment {
....
//Creating the interface
public interface ButtonListener {
//This method will be called in the main activity. Whatever is passed in as the parameter can be used by the main activity
public void ButtonPressed(int myInt);
}
//Getting an instance of the interface
ButtonListener updateListener;
//Getting a reference to the main activity when the fragment is attached to it.
//The activity reference is bound to the instance of the interface.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Ensures the activity implements the callback interface
try {
updateListener = (DayUpdateButtonListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString());
}
}
....
//On the button click call the method through the activity reference from the onAttach() method
//Creating an int object to pass into the method.
int myNewInt = 5;
myButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
updateListener.ButtonPressed(myNewInt);
}
});
}
Finally in the main activity simply implement the interface and add the method from it.
public class CollectionDemoActivity extends FragmentActivity implements DemoObjectFragment.ButtonListener {
....
#Override
public void ButtonPressed(int myInt) {
//Update the object with myInt
}
}