Resume Activity from Fragment - android

I tried several times to invoke Resume method of MainActivity from the Fragment,
calling simply onResume(); nothing in result.
code for resume method
protected void onResume() {
all.clear();
outgoing.clear();
incoming.clear();
getFromSdcard();
super.onResume();
}
I want to call this method from fragment.

Enhancing #cricket_007 response :
You can invoke onResume from the parent Activity, but just like you have seen, onResume has protected access blocking you from calling it.
There is a small visibility workaround that allows you to do it.
1 - Implement this method on your activity
public void myOnResume(){
this.onResume();
}
2 - Then on your fragment you can invoke
public void myFragmentMethod(){
// make sure to double check casts (to YourActivity) like these before invoking
((YourActivity) getActivity()).myOnResume();
}
Conclusion and recommendation : Even though it is not recommended that you implement it this way, it can be done like I said.
In my opinion, what you should do is :
1 - Have all the functionalities of your onResume() method inside a proper method of your own (you name it!) like :
public void clearData() {
all.clear();
outgoing.clear();
incoming.clear();
getFromSdcard();
}
2 - Then you could just separate all these functionalities from onResume() and still have them invoked like
protected void onResume() {
super.onResume();
clearData();
}
3 - Invoke it on your fragment like (previously shown)
public void myFragmentMethod(){
// make sure to double check casts (to YourActivity) like these before invoking
((YourActivity) getActivity()).clearData();
}
Let me know how it went.
Regards,

You are calling the Fragments onResume()
You can try getActivity().onResume(), but you really should make a method to do whatever code you need rather than explicitly call lifecycle methods.

Create an Interface
interface OnParentActivityResumed {
fun onActivityResumed()
}
implement the interface in the fragment
class MyFragment: Fragment(), OnParentActivityResumed{
override fun onActivityResumed() {
//[YOUR CODE WHEN PARENT ACTIVITY RESUMED]
}
}
on parent activity onResume add
override fun onResume() {
super.onResume()
myFragment.onActivityResumed()
}

Related

how to run code in fragment only if it is visible to user

i have 4 fragments, in each one i want to use accelerometer that do different thing. My problem is that when i swipe to second fragment and shake my phone it runs code from first fragment because it is a part of same activity. I override onResume and onPause methods but it won't work right (only work when i swipe to fragment 3 than sensor is unregistered. I have tried something with if function inside onSensorChanged method and put some public static int fragmentPageNumber and change it onCreate method of every fragment but it is changed to fragment 2 when activity is started so i must then swipe thru fragments for code to start working right...but i think the problem is on overriding onResume and onPause methods right...
#Override
public void onResume() {
super.onResume();
sensorManager.registerListener(accelerometerEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
#Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(accelerometerEventListener);
}
Depending on a few factors, you might be able to override setUserVisibilityHint() in your Fragments. If your Fragments are added to a FragmentPagerAdapter or a FragmentStatePagerAdapter, these adapters will call this method on the Fragment when it becomes visible. In your case, in your Fragments, you could do something like:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
sensorManager.registerListener(accelerometerEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
} else {
sensorManager.unregisterListener(accelerometerEventListener);
}
}
You can try to create an extension function on Kotlin to run a block of code only when the fragment is attached to the Activity. So whenever the context is created u can be sure that the fragment has been attached to an activity and so shown to the user.
internal inline fun Fragment.runIfFragmentIsAttached(block: () -> Unit) {
context?.let { block() }
}

Null object reference while trying to pass array list using interface

Hello so I am trying to pass an array list from my activity to the fragment and this is what I did :
FirstActivity :
AdminInterface instanceForInterface;
OnCreate
//
System.out.println(results.size) ; //works fine
instanceForInterface.onDataRecieved(results); // here I am getting the exception
//
public interface AdminInterface {
void onDataRecieved(ArrayList <Result> response);
}
public void setInterface(UserFragment anInterface) {
this.instanceForInterface = anInterface;
}
Fragment
OnActivityCreated
((FirstActivity) getActivity()).setInterface(this);
#Override
public void onDataRecieved(ArrayList<Result> response) {
processData(response);
}
Exception
Attempt to invoke interface method 'void **************.onDataRecieved(java.util.ArrayList)' on a null object reference
What I think :
I am calling this line
instanceForInterface.onDataRecieved(results); in OnCreate()
before the initialisation of
((FirstActivity) getActivity()).setInterface(this); in OnActivityCreated()
Solution Please ??
Thank You
The problem is that your fragment's onActivityCreated() method is invoked after your activity's onCreate() method.
The smallest change you can make to achieve the behavior you want is to use the onResumeFragments() method in your activity. That is, delete the line instanceForInterface.onDataRecieved(results); from your onCreate and add this code:
#Override
protected void onResumeFragments() {
super.onResumeFragments();
instanceForInterface.onDataRecieved(results);
}
onResumeFragments() will be invoked by the system after both your activity's onCreate() and your fragment's onActivityCreated() methods.
That being said, chances are quite good that you would be better off with a different approach entirely. For instance, you could have your activity expose a getter for results and have your fragment retrieve the results to work with (rather than have your activity store a reference to your fragment).
Further reading about the Activity and Fragment lifecycles:
https://developer.android.com/guide/components/activities/activity-lifecycle.html
https://developer.android.com/guide/components/fragments.html

Is there any way to Detect userInterations in Android fragments?

Could any one help me out with this situation.
I have implemented OnUserInteraction() method for Android Activity it is working fine for me.
But I want it for Fragments too.How can i able call OnUserInteraction() or is there any another way to identify userInteraction with the UI.
#Sunil's answer causes java.lang.StackOverflowError so I corrected it. Below code works smoothly
Create a java class in your app named UserInterationListener and put below code there
public interface UserInteractionListener {
void onUserInteraction();
}
Then create an instance variable in your activity, for this interface as below
private UserInteractionListener userInteractionListener;
Then implement a setter method for this variable, in your activity.
public void setUserInteractionListener(UserInteractionListener userInteractionListener) {
this.userInteractionListener = userInteractionListener;
}
Now override the onUserInteraction method of your activity and if the listener variable is not null, invoke the interface method.
#Override
public void onUserInteraction() {
super.onUserInteraction();
if (userInteractionListener != null)
userInteractionListener.onUserInteraction();
}
Now, in your fragment class, implement UserInteractionListener as below
public myFragment extends Fragment implements UserInteractionListener
also override interface's method
#Override
public void onUserInteraction(){
//TODO://do your work on user interaction
}
then in your fragment invoke your activity's userinteraction setter method like below
((YourActivity) getActivity()).setUserInteractionListener(this);
this last part is important.
There is another way around.
Create a listener in your activity as below
public interface UserInteractionListener {
void onUserInteraction();
}
Then create an instance variable in your activity, for this interface as below
private UserInteractionListener userInteractionListener;
Then implement a setter method for this variable, in your activity. (You can even keep a List of eventlistener objects, if you want to pass same userinteraction to multiple consumers)
public void setUserInteractionListener(UserInteractionListener userInteractionListener) {
this.userInteractionListener = userInteractionListener;
}
Now override the onUserInteraction method of your activity and if the listener variable is not null, invoke the interface method.
#Override
public void onUserInteraction() {
super.onUserInteraction();
if (userInteractionListener != null)
userInteractionListener.onUserInteraction();
}
Now, in your fragment class, register for events as below
((YourActivity) getActivity()).setUserInteractionListener(new YourActivity.UserInteractionListener() {
#Override
public void onUserInteraction() {
// Do whatever you want here, during user interaction
}
});

Otto unregistering the same instance

I have a BaseFragment which within it's onCreateView method, creates a MyObject class. Both of these are inside a ViewPager.
Two different fragments extends from the BaseFragment - FragmentA, FragmentB.
This means FragmentA and FragmentB both have their own instances of the MyObject object.
Within the BaseFragment, I call myObject.initialise(); on the MyObject object from the onStart(); method and cleanUp(); from the onStop();
#Override
public void onStart()
{
super.onStart();
myObject.initialise();
}
#Override
public void onStop()
{
myObject.cleanUp();
super.onStop();
}
Again - this lives inside the BaseFragment so both FragmentA and FragmentB have this in their lifecycle.
The initialise(); function and cleanUp(); functions look like this:
#Override
public void initialise()
{
BusManager.register(this);
}
#Override
public void cleanUp()
{
BusManager.unregister(this);
}
FragmentA will generally close first and it successfully unregisters. When FragmentB closes however, it crashes because it think this was not registered.
I checked the memory address of this and it appears that it tries to unregister the same thing twice.
Missing event handler for an annotated method. Is class com.example.app.MyObject registered?
Why is it doing this? I have made sure that MyObject is a new instance.
For the comment above, note that onDestroy() is not necessary called:
https://developer.android.com/reference/android/app/Activity.html#onDestroy()
You should not count on that for Otto's register / unregister call.
In regarding to Subby's question: I've had scenarios where onStart() / onStop() being called twice. What I ended up is placing a try-catch block. Definitely not a clean solution, but that's how I do before finding out why the lifecycle is messed up.

Method to override when layout is destroyed in Android

I have a custom component which extends LinearLayout, I need to execute certain statements when Layout is destroyed or removed. (or about to be removed)
One way is to check for onPause() or onDestroy() of an activity and call methods of the custom component. But I want to remove that overhead from the activity.
So that custom component itself can handle when layout is detached. But I dint find the suitable method to override (to detect the event) when layout is removed. Is there a way to handle this, or we need to use onPause() and onResume() method of activity ?
I had success overriding the onAttachedToWindow() and onDetachedFromWindow() methods:
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// View is now attached
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// View is now detached, and about to be destroyed
}
You can have your custom view listen to its own eventss. I suggest using View.OnAttachStateChangeListener and listening to onDetach event.
#Override
void onViewDetachedFromWindow(View v) {
doCleanup();
}
It is dangerous to rely on the "destruction" of a layout to execute statements, as you're not directly in control of when that happens. The accepted way and good practice is to use the activity's lifecycle for that.
But if you really want to tie your component to that lifecycle, I suggest your component implements an interface (something like Removable), and do something like that in your base activity classe (that all your activities extend):
protected Set<Removable> myRemovableItems = new HashSet<Removable>();
#Override
public void onPause() {
super.onPause();
for (Removable removable : myRemovableItems) {
removable.remove();
}
}
The interface:
public interface Removable {
void remove();
}
Then each time you add one of your custom component from an activity, you add the component to the internal set of Removable of the activity, and its remove method will be automatically called each time the activity is paused.
That would allow you to specify what to do when onPause is called within the component itself. But it wouldn't ensure it's automatically called, for that you'll have to do it in the activity.
Note: you can use onStop instead of onPause depending on when you want the removal to occur.

Categories

Resources