I am trying to find a callback for my FragmentActivity that happens 'after' all of the fragments have called 'onCreateView'.
The reason for this is that my Fragment implement my interface:
public interface LifeCycleFragment {
public void onResumeFragment();
}
and when i call the fragment from MyActivity:
class MyActivity extends Activity
onCreate()
fragment.onResumeFragment()
getActivity() ends up being null:
class MyFragment extends Fragment implements LifeCycleFragment
#Override
public void onResumeFragment() {
Log.e(TAG, "- ON RESUME -");
FragmentActivity activity = getActivity();
// *****ACTIVITY IS NULL HERE AND THAT'S A PROBLEM ***//
I am not sure how to tackle this problem and any help would be appreciated.
Place getActivity() in override onActivityCreated method, and save it in the class for onResumeFragment(). I hope the Activity is still kept the same during onPause().
Would you like sample code to communicate between Fragment and Activity? I posted an answer in SO about it # Passing data between fragments contained in an activity. The respective Google webpage is # Communicating with Other Fragments.
Good luck and have fun...
Related
I have 1 main activity and 4 fragments. Each fragment have the same method name, each does a different thing (initializing data is the same, what each fragment does with the data is different).
At the moment I check which fragment is active and I call that method:
if (getSupportFragmentManager().findFragmentByTag("f1") != null)
Objects.requireNonNull((FragmentF1) getSupportFragmentManager().findFragmentByTag("f1")).setupData(true);
else if (getSupportFragmentManager().findFragmentByTag("f2") != null)
Objects.requireNonNull((FragmentF2) getSupportFragmentManager().findFragmentByTag("f2")).setupData(true);
I want to call that method, no matter the fragment I have now. Is it possible?
Also, the requireNonNull is there to avoid the lint warning despite the null check I do one line above, is there a way to make this code cleaner?
You can create base class or abstract class for your fragments
public abstract class BaseFragment extends AppCompatActivity {
abstract void setupData(boolean b);
}
Then each fragments inherit from BaseFragment class and overrides setupData(boolean b).
After you find the fragment check if he instace of BaseFragment and call the method
Fragment fragment = getSupportFragmentManager().findFragmentByTag("tag")
if (fragment instanceof BaseFragment){
fragment.setupData(true);
}
you can declare this method in your activity in which take fragment as parameter and in each time you call this method check on passed fragment and do your logic based on it.
public static void initData(Fragment fragment){
if (fragment instanceof FirstFragment){
// Do your logic here
}else if(fragment instanceof SecondFragment){
// Do your logic here
}
}//initData()
When you should call the method ?
I think in your cause you should use Event bus,
so with eventbus when something happen you should post the event to the active fragment
EventBus.getDefault().post("your event here");
and register the event in the fragments so when the fragment is currently launched and the event posted the fragment will receive the event
read more about event bus
Im trying to figure a way how to call an activity that an adapter has started. Is there a way to get the instance of the activity from startactivity and make a method call into the activity ?
I'ved got an adapter that has a list
public class LanguageDownloadRVAdapter extends RecyclerView.Adapter<LanguageDownloadRVAdapter.DownloadViewHolder>{
And in this adapter, it starts a particular activity called MainActivity
context.startActivity(new Intent(context, MainActivity.class));
((Activity)context).finish();
Here is the MainActivity that it starts
public class MainActivity extends AppCompatActivity implements IabBroadcastListener{
How can I make a call from the adapter to a method in the MainActivity. (im just trying to perform inapp purchase which is implemented in the MainActivity). so how can i do something like this.
mainactivity.perform_inapp_purchase();
Try to use EventBus for passing data between activity and list adapter. You can do it in the same way for passing data between activity and fragment.
This work the same way as storing data in global variable (in a fancier way)
In the adapter:
Add a new Field private Context mContext;
In the adapter Constructor add one more parameter as below, and assign it into class level variable:
public LanguageDownloadRVAdapter(......,Context context){
//your code.
this.mContext=context;
}
In the Adapter where you want to call Activity's perform_inapp_purchase() method:
if(mContext instanceof MainActivity){
((MainActivity) mContext).perform_inapp_purchase();
}
More Generalized Approach:
If you need to use this same adapter for more than one activity then :
Create an Interface
public interface InAppPerchaceInterface{
void perform_inapp_purchase();
}
Implement this interface in activities
Then in Adapter, call like below:
if(mContext instanceof InAppPerchaceInterface){
((InAppPerchaceInterface) mContext).perform_inapp_purchase();
}
You can store the instance in the application class, but you should be careful about the memory leaks.
In the onCreate of your activity
protected void onCreate(Bundle savedInstanceState)
{
// get the instance using this and store it in the application class or in the place that you want to call from it
}
From where will you call your method?
I didn't understand the situation.
I have an activity A which contain 7 fragment. For communication between fragment to activity and fragment to fragment, My activity explictly declare Fagment interface of all the 7 fragment.
The Syntax is like
class A extends Activity implements B.onInteraction, C.onInteraction, D.OnInteration .... {
}
This becomes long and i don't like explicity declaring it in on top of activity.
The other solution i can think of is define a method setOnInteractionListener() in each fragment and pass anonymous class to it like.
class B extends Fragment {
public void setOnFragmentInteractionListener(OnFragmentInteraction listener) {
}
}
By this way i don't need to override onAttach() of fragment and i don't need to explicty declare fragment interface on top.
My Question is: Is this a good way of doing things? What are the cons of using anonymous class here. Is there any better approach to do this or i should stick to explictly declaring interface while creating activity.
I'm not sure if I understand the question cause I'm a beginner. In my oppinion can create an interface for all your fragments:
public interface ActivityListener {
void onCall(Fragment fragment);
}
your activity:
public class MainActivity extends AppCompatActivity implements ActivityListener {
#Override
public void onCall(Fragment fragment) {
switch (fragment.getTag()) {
case YOUR_TAG:
Log.d("listener", "called");
break;
}
}
}
in your fragment use onAttach() method to get the interface.
I prefer to use EventBus (especially https://github.com/greenrobot/EventBus, someone prefer http://square.github.io/otto/) to communicate between Fragments and Activity.
You need to register (and unregister) the listener (activity, for example, or another fragment) and create a method with onEvent(<CustomEventclass> event);
EventBus.getDefault().register(this); //and unregister
And just post the event from the fragment like
EventBus.getDefault().post(<CustomEventClass> instance);
Making BaseFragment and pass the listener is also a normal way. This is just a developer choice.
Im trying to implement fragment to activity communication.
Went through android developer doc where an Activity object is passed to onAttach life cycle and set up the Fragment-Activity communication.
This documentation asks to pass Context object instead of Activity. I replaced all the Activity objects by Context objects in the life cycle method onAttach. But it is throwing a NullPointerException while calling the method of the interface from Fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
colourChangerInterface = (ColourChangerInterface) context;
}
catch (Exception exp){
System.out.println("error!");
}
}
Can anyone please give a small example of the usage in the new way ?
Thanks
Edit :
Found this link where detail discussion is there on the same issue.
The issue is because of the broken API 'onAttach()'; it doesn't get called at all when Context object is passed.
A simple and quick solution found from the above link is to move the code from onAttach to onCreate.
Here is a small example that will describe you the communication between Activity and Fragment. Suppose you have a Interface ICommunication. This is given below:
public interface ICommunication {
public void testMethod();
}
Now you have a Activity name MainActivity that implements ICommunication then it must have implements the method testMethod(). This method will like this:
#Override
public void testMethod() {
Toast toast = Toast.makeText(getActivity(), "It's called from Fragment", Toast.LENGTH_SHORT).show();
}
Now, suppose this MainActivity belongs a Fragment name TestFragment . If you want to access testMethod() of MainActivity from TestFragment then you can simply call using this way :
((ICommunication)getActivity()).testMethod();
Here , TestFragment must be hold on MainActivity.
My related answer with source is here
Thats it :)
This question already has answers here:
Call an activity method from a fragment
(18 answers)
Closed 9 years ago.
I am trying to call a method in an activty from a Fragment screen.
I have a method called myMethod() which is in an activity called MyActivity;
I have a fragment called Screen1Fragment.
I would like to call MyActivity.myMethod() from inside the Screen1Fragment but I am not sure how to do this.
Previously the Screen1Fragment was an activity and so I was extending MyActivity so that I could directly call
myMethod().
But I have had to change the activity to a fragment for sliding tabs usage.
Thanks in advance.
Use getActivity() in your fragment.
MyActivity activity = (MyActivity) getActivity();
activity.myMethod();
if you are not sure if your fragment is attached to MyActivity then
Activity activity = getActivity();
if(activity instanceof MyActivity){
MyActivity myactivity = (MyActivity) activity;
myactivity.myMethod();
}
You should make your fragment totally independant of the activity you are attaching it to. The point of Fragments is that you can re-use them in different contexts with different activities. To achieve that and still being able to call methods from your Activity the following pattern in recommended in the official documentation.
In your fragment:
define a public interface with the method
public interface MyFragmentCallback{
public void theMethod();
}
define a field and get a cast reference:
private MyFragmentCallback callback;
public void onAttach(Activity activity){
callback = (MyFragmentCallback) activity
super.onAttach(activity);
}
In your Activity
implement MyFragmentCallback in the class definition.
implement theMethod() in your activity (Eclipse will ask you to do so)
Then, from your fragment, you can call callBack.theMethod()
The difference between this and simply calling your method on getActivity() is that your fragment is not paired with this specific activity anymore. So you may re-use it with other activity for example one for phones and the other for tablets.
If the method is the static method of MainActivity, something like:
public static void someMethod(){}
Then, it is pretty straightforward. Just call
MainActivity.someMethod()
However, I guess what you really want is to access some function from the Activity class. Then you can use the following code in the Fragment view creater
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
container.getContext().someMethod();
}