在片段和活动之间进行交流-最佳做法

问题描述 投票:55回答:9

这个问题主要是为了寻求关于处理我的应用程序的最佳方法的意见。 我有一个活动正在处理三个片段。 片段A有一个可单击元素(照片),片段B有4个可单击元素(按钮)。 单击照片后,另一个片段仅显示详细信息。 我正在使用ActionBarSherlock。

屏幕截图

前进和后退按钮需要将照片分别更改为下一个或上一个姿势。 我可以将照片和按钮放在同一片段中,但想让它们分开,以防我想在平板电脑中重新排列它们。

我需要一些建议-我应该结合片段A和片段B吗? 如果没有,我将需要弄清楚如何为3个可点击项实现接口。

我考虑过使用Roboguice,但是我已经使用SherlockFragmentActivity进行了扩展,所以这是不可行的。 我看到了Otto的提法,但是我没有看到关于如何将其包含在项目中的优秀教程。 您认为最佳设计实践应该是什么?

我还需要帮助弄清楚如何在片段和活动之间进行通信。 我想在应用程序中保留一些“全局”数据,例如pose ID。 除了股票android开发人员的信息外,我还能看到一些示例代码吗? 那并不是全部有帮助。

顺便说一句,我已经将每个姿势的所有信息存储在SQLite数据库中。 那是容易的部分。

android android-fragments android-activity communication
9个回答
75
投票

在活动和片段之间进行通信的最简单方法是使用接口。 这个想法基本上是在给定的片段A内定义一个接口,然后让活动实现该接口。

一旦实现了该接口,您就可以在其覆盖的方法中做任何您想做的事情。

接口的另一个重要部分是您必须从片段中调用abstract方法,并记住将其强制转换为活动。 如果处理不正确,它将捕获ClassCastException。

Simple Developer Blog上有一个很好的教程,介绍了如何完全执行此类操作。

希望对您有帮助!


23
投票

建议在片段之间进行通信的方法是使用由主Activity管理的callbacks \\ listener。

我认为此页面上的代码非常清楚: http : //developer.android.com/training/basics/fragments/communicating.html

您还可以引用IO 2012 Schedule应用程序,该应用程序被设计为事实上的参考应用程序。 可以在这里找到: http : //code.google.com/p/iosched/

另外,这是一个具有良好信息的SO问题: 如何在片段之间传递数据


11
投票

它是通过Callback接口实现的:

首先,我们必须创建一个接口:

public interface UpdateFrag {
     void updatefrag();
}

在活动中执行以下代码:

UpdateFrag updatfrag ;

public void updateApi(UpdateFrag listener) {
        updatfrag = listener;
}

从必须在Activity中触发回调的事件中得出:

updatfrag.updatefrag();

在Fragment实现中, CreateView的接口执行以下代码:

 ((Home)getActivity()).updateApi(new UpdateFrag() {
        @Override
        public void updatefrag() {
              .....your stuff......
        }
 });

4
投票

我制作了一个注释库,可以为您进行转换。 看一下这个。 https://github.com/zeroarst/callbackfragment/

@CallbackFragment
public class MyFragment extends Fragment {

    @Callback
    interface FragmentCallback {
       void onClickButton(MyFragment fragment);
    }    
    private FragmentCallback mCallback;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt1
                mCallback.onClickButton(this);
                break;
            case R.id.bt2
                // Because we give mandatory = false so this might be null if not implemented by the host.
                if (mCallbackNotForce != null)
                mCallbackNotForce.onClickButton(this);
                break;
        }
    }
}

然后,它生成您片段的子类。 并将其添加到FragmentManager。

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction()
            .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM")
            .commit();
    }

    Toast mToast;

    @Override
    public void onClickButton(MyFragment fragment) {
        if (mToast != null)
            mToast.cancel();
        mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT);
        mToast.show();
    }
}

4
投票

要在ActivityFragment之间进行通信,有几种选择,但是经过大量阅读和大量经验,我发现可以通过以下方式恢复它:

  • Activity要与子Fragment进行通信=>只需在Fragment类中编写公共方法,然后让Activity调用它们即可
  • Fragment希望与父代进行交流Activity =>这需要更多的工作,正如官方的Android链接https://developer.android.com/training/basics/fragments/communication所建议的那样,定义一个好主意一个由Activity实现的interface ,它将与任何要与Fragment通信的Activity建立一个契约。 例如,如果您具有FragmentA ,它想与包含它的任何activity进行通信,则定义FragmentAInterface ,它将定义FragmentA可以为决定使用它的activities调用哪种方法。
  • 一个分Fragment想与其他分Fragment通信=>这是您遇到最“复杂”情况的情况。 因为你可能需要从FragmentA数据传递给FragmentB,反之亦然,这可能会导致我们定义2个接口, FragmentAInterface将由执行FragmentBFragmentAInterface将由执行FragmentA 那将使事情变得混乱。 想象一下,如果您还有更多的Fragment ,甚至父activity想与他们进行交流。 好了,这种情况是为activity及其fragment s建立共享ViewModel的绝佳时机。 更多信息, 请参见https://developer.android.com/topic/libraries/architecture/viewmodel 基本上,您需要定义一个SharedViewModel类,该类具有要在activityfragments之间共享的所有数据,这些fragments将需要在它们之间进行数据通信。

ViewModel情况下,最后使事情变得非常简单,因为您不必添加额外的逻辑即可使事情变得肮脏且混乱。 另外,它还允许您从Controlleractivitiesfragments )中分离数据的收集(通过调用SQLite数据库或API)。


2
投票

在活动,片段,服务等之间进行通信的方法有多种。显而易见的一种方法是使用接口进行通信。 但是,这不是有效的沟通方式。 您必须实现监听器等。

我的建议是使用事件总线。 事件总线是一种发布/订阅模式的实现。

您可以订阅活动中的事件,然后可以在片段等中发布该事件。

在我的博客文章中,您可以找到有关此模式的更多详细信息,以及一个示例项目以显示用法。


1
投票

我不确定我是否真的了解您要做什么,但是建议的在片段之间进行通信的方法是对Activity使用回调,而不是直接在片段之间进行回调。 看到这里http://developer.android.com/training/basics/fragments/communicating.html


0
投票

您可以在片段中创建带有函数声明的声明公共接口,并在活动中实现该接口。 然后,您可以从片段中调用该函数。


0
投票

我正在使用Intent将动作传达回主要活动。 主要活动是通过重写onNewIntent(Intent intent)来监听这些内容。 例如,主要活动将这些动作转换为相应的片段。

因此,您可以执行以下操作:

public class MainActivity extends Activity  {

    public static final String INTENT_ACTION_SHOW_FOO = "show_foo";
    public static final String INTENT_ACTION_SHOW_BAR = "show_bar";


   @Override
   protected void onNewIntent(Intent intent) {
        routeIntent(intent);
   }

  private void routeIntent(Intent intent) {
       String action = intent.getAction();
       if (action != null) {               
            switch (action) {
            case INTENT_ACTION_SHOW_FOO:
                // for example show the corresponding fragment
                loadFragment(FooFragment);
                break;
            case INTENT_ACTION_SHOW_BAR:
                loadFragment(BarFragment);
                break;               
        }
    }
}

然后在任何片段中显示foo片段:

Intent intent = new Intent(context, MainActivity.class);
intent.setAction(INTENT_ACTION_SHOW_FOO);
// Prevent activity to be re-instantiated if it is already running.
// Instead, the onNewEvent() is triggered
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
getContext().startActivity(intent);
© www.soinside.com 2019 - 2024. All rights reserved.