对象到片段通信

Object to Fragment Communication

我可能错过了接口的概念,因为出于某种原因,这似乎让我难以理解。这是我的场景:

期望的结果

我想要一个非片段/非activity Java class Routines.java 当后台线程在Routines.java完成。

当前行为

我目前从 Routines.java 内部通过广播 FragmentA 已注册并正在侦听的意图与 FragmentA 通信。虽然这个解决方案有效,但我不禁觉得这不是正确的做法。

问题

我想知道是否可以实现一个接口以便我可以摆脱广播意图,或者通常是否有更好的方式从 non-fragment/activity classes 进行通信至 fragments/activities.

实现从片段到 activity 的接口的解决方案不是我正在寻找的,因为我已经知道该怎么做,但如果通信的一侧我似乎无法让它工作不是 activity 或片段。

我试过的

//in Routines.java

public class Routines implements FragmentA.OnRoutineFinishedListener

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

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

我的主要问题是,当我不能使用像这样的 onAttach(Activity activity){ ... set up callback here by casting activity as the interface} 方法的典型方法时,我不确定如何调用这些方法:

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

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

当它是 activity 的片段时,上面的代码使 mCallback 对我可用,这样我就可以自由调用实现方法,但我没有那么奢侈,因为我正在尝试获得触发片段内函数的非片段。

始终是问题是如何实际触发 Routines 最终触发 FragmentA 中的 finished 方法的条件。如果能帮助我理解如何实现这一点,我将不胜感激。

你看过观察者模式了吗?我认为这是可行的方法。 祝你好运。

看一个例子here

如您所见,您可以将它用于一个或多个观察者。

在片段上调用代码的最简单方法是保存对片段的引用。仅仅因为你的对象不是 activity 并不意味着你不能将 Fragment 引用传递给 Routines 对象,只是要小心,不要因为持有引用的时间超过你需要的时间而浪费内存。

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

Calling a Fragment method from a parent Activity

您是否考虑过使用事件总线系统 ala otto?

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

您可以 post 在您的 Routines.java class

中举办活动
bus.post(new FinishedEvent(position));

然后你可以在你的片段中订阅接收事件

bus.register(this);

@Subscribe public void OnRoutineFinished(FinishedEvent event) {
     // TODO: React to the event somehow!
}

在查看@gatunox 的建议("observer pattern")后,我对该模式进行了一些研究,发现它确实可以满足我的需要。我喜欢可以通知多个对象状态更改的想法。我实施了以下措施来实现我的目标:

片段A

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();

现在当 Routines.java 执行那行时 FragmentAupdate 方法被触发。

我相信你应该有不同的想法。让我们先问谁启动后台任务工作?如果片段是调用者,那么 interface/listener 方法将像 :

//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();

} 

您还可以使用线程和处理程序通过将处理程序传递给 class 例程并在 class post 消息中传递给此处理程序来执行此操作。

如果片段不是启动后台任务的部分,并且您没有来自片段的实例或侦听器或 activity 将其保存在例程 class 中,那么广播意图应该没问题.