0

I might be missing the concepts of interfaces because this for some reason seems to elude me. Here is my scenario:

Desired Outcome

I would like a non-fragment / non-activity Java class Routines.java to trigger a method inside FragmentA when background threads inside Routines.java are complete.

Current Behavior

I currently communicate to FragmentA from inside Routines.java by broadcasting an intent that FragmentA has registered and is listening for. Although this solution works I can't help but feel that it is not the correct way of doing this.

Questions

I would like to know if it's possible to implement an interface so that I can get rid of the broadcast intents or if in general there is a better way to communicate from non-fragment/activity classes to fragments/activities.

The solution for implementing interfaces from a fragment to activity is not what I am searching for as I already know how to do that but I can't seem to get it working if one side of the communication is not an activity or fragment.

What I've Tried

//in Routines.java

public class Routines implements FragmentA.OnRoutineFinishedListener

public void finished(int position){
 ...
}

//in FragmentA
public interface OnRoutineFinishedListener {
        public void finished(int position);
    }

My main issue is that I'm not sure exactly how to call the methods when I can't use the typical approach of using onAttach(Activity activity){ ... set up callback here by casting activity as the interface} approach like this:

public void onAttach(Activity activity){
        super.onAttach(activity);

        try {
            mCallback = (SomeFragment.SomeListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement SomeListener");
        }
    }

When it's fragment to activity then the above code makes mCallback available to me so that I can freely call implementing methods but I don't have that luxury because I'm trying to get a non-fragment to trigger a function inside a fragment.

Always the issue is how to actually trigger the condition where Routines finally triggers the finished method inside FragmentA. I would greatly appreciate some help in understanding how to accomplish this.

Max Worg
  • 2,932
  • 2
  • 20
  • 35

5 Answers5

1

Have you looked at Observer Pattern?, i think this is the way to go. Good luck.

look one example here

As you can see, you can use it for one or many observers.

Gatunox
  • 532
  • 4
  • 14
  • +1 for pointing me in the right direction. I posted a complete answer with code to show how I implemented the solution to my issue so that other people can see how it's done. Thank you very much for your suggestion. – Max Worg Feb 04 '15 at 12:11
1

After reviewing @gatunox's suggestion (the "observer pattern") I did some research into this pattern and I found that it would indeed work for my needs. I like the idea that multiple objects can be notified of state changes. I implemented the following to achieve my goal:

FragmentA

public class FragmentA extends Fragment implements Observer{
 ...
 @Override
    public void update(Observable observable, Object data) {

        Logging.log("FragmentA observed the following from Routines: "+data);

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                Bundle savedInstanceState) {

        routines = new Routines(getActivity().getApplicationContext());

        ((MainActivity)getActivity()).actionObserver.addObserver(this);

Routines.java

((MyApp)appContext).actionObserver.updateStatus("Routine finished!!");

ActionObserver.java

public class ActionObserver extends Observable {


    public void updateStatus(String message){

        setChanged();
        notifyObservers(message);
    }

}

MainActivity.java

MyApp bApp = (MyApp) getApplication();
actionObserver = bApp.getObserver();

Now when Routines.java executes that line FragmentA's update method is triggered.

Max Worg
  • 2,932
  • 2
  • 20
  • 35
0

The easiest way to invoke code on a fragment is to hold a reference to it. Just because your object isn't an activity doesn't mean you can't pass a Fragment reference to the Routines object, just be careful you don't waste memory by holding references longer than you need to.

FragmentA fragment = (FragmentA) getFragmentManager().findFragmentById(R.id.example_fragment);
fragment.finished(myInt); 

Calling a Fragment method from a parent Activity

Community
  • 1
  • 1
Dave S
  • 3,378
  • 1
  • 20
  • 34
0

Have you considered using an event bus system ala otto?

http://square.github.io/otto/

You can post an event inside your Routines.java class

bus.post(new FinishedEvent(position));

Then you can subscribe to receive events in your fragment

bus.register(this);

@Subscribe public void OnRoutineFinished(FinishedEvent event) {
     // TODO: React to the event somehow!
}
Eoin
  • 4,050
  • 2
  • 33
  • 43
0

I believe you should think differently about it. Lets start by asking Who starts the background task to work ? If the fragment is the caller then the interface/listener approach will work like :

//inside fragment 
Routines.doTaskInbackground(new TaskListener(){

  onComplete(){ // task completed }
   //do your work here
});


//inside routines
public static void doTaskInbackground(TaskListener listener){

//on complete
listener.onComplete();

} 

You can also use threads and handlers to do this by passing handler to class routines and inside the class post messages to this handler.

If the fragment is not the part that starts the background task and you have no instance or listener from fragment or the activity holding it inside routines class , then the broadcast intent should be okay.

MSaudi
  • 4,442
  • 2
  • 40
  • 65