题 在片段和活动之间进行通信 - 最佳实践


这个问题主要是征求关于处理我的应用程序的最佳方式的意见。我有三个片段由一个活动处理。片段A有一个可点击元素照片,片段B有4个可点击元素按钮。另一个片段只显示单击照片时的详细信息。我正在使用ActionBarSherlock。

Screen shot

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

我需要一些建议 - 我应该将碎片A和B结​​合起来吗?如果没有,我将需要弄清楚如何为3个可点击项目实现一个界面。

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

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

顺便说一句,我已经在SQLite数据库中存储了每个姿势的所有信息。这很容易。


46
2018-01-09 22:52


起源


实际上你可以使用Rogoguice和ActionbarSherlock一起看看 github.com/rtyley/roboguice-sherlock。 - rubenlop88
Otto更简单,打包为独立的.jar文件,您可以将其放在应用程序的libs /文件夹中。 - rubenlop88
@rubenlop88添加一个库只是为了将一些数据从Fragment传递给Activity? - Marian Paździoch


答案:


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

一旦它实现了该接口,您可以在它覆盖的方法中执行任何您想要的操作。

接口的另一个重要部分是您必须从片段中调用抽象方法并记住将其强制转换为您的活动。如果没有正确完成,它应该捕获ClassCastException。

有一个很好的教程 简单开发者博客 关于如何做到这一点。

我希望这对你有所帮助!


61
2017-08-19 20:38



这就是我最后做的事情。谢谢。 - Kristy Welsh
有谁知道为什么Android开发者页面上关于使用警报对话框的示例不使用接口与活动进行通信? developer.android.com/reference/android/app/... - cjayem13
或使用EventBus github.com/greenrobot/EventBus - powder366
接口很好。但是对于更松散的耦合,请使用广播听众。 - DeaMon1
现代的方法是使用实​​际上解耦你的项目代码的事件,这个答案来自2014年,虽然在某种程度上起作用,但不应该是这种情况的唯一解决方案! - Eenvincible


建议的片段之间通信方法是使用由主Activity管理的回调\侦听器。

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

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

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


22
2018-01-09 23:13





它由回调接口实现: 首先,我们必须创建一个接口:

public interface UpdateFrag {
     public void updatefrag();
    }

在活动中执行以下代码:

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

来自回调必须在活动中触发的事件:

updatfrag.updatefrag();

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

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

7
2017-09-03 17:48





有几种方法可以在活动,片段,服务等之间进行通信。显而易见的方法是使用接口进行通信。但是,它不是一种有效的沟通方式。你必须实现听众等。

我的建议是使用活动巴士。事件总线是发布/订阅模式实现。

您可以订阅活动中的活动,然后您可以将这些活动发布到您的活动中。

这里 在我的博客文章中 你可以找到关于这种模式的更多细节 一个示例项目 显示用法。


2
2018-04-08 13:45





我制作了一个可以为你做演员的注释库。看一下这个。 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();
    }
}

2
2018-06-22 08:14





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


1
2018-01-09 23:08



是的,这种方式似乎令人困惑,我有两个片段,需要通过活动以某种方式相互沟通。有关于如何做到这一点的更好的教程吗? - Kristy Welsh
@KristyWelsh:我想知道你是否已经形成了自己的概念 Fragments 他们真的是以及如何运作而不是掌握了实际的概念 Fragment 设计目标。与之沟通的概念 Activity 运用 interfaces 与拥有一个没有什么不同 Activity 实行 View.OnClickListener 所以a Button 按下导致项目被添加到a ListView (例如)。你可能有一个 Activity 使用FragmentA和FragmentB但不是FragmentC - 在这种情况下,让FragmentA“知道”如何直接与FragmentC对话的概念是多余的。 - Squonk


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


0
2018-06-07 13:52





我正在使用Intents将操作传达回主要活动。主要活动是通过覆盖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);

0
2017-12-16 11:17





在...之间进行通信 Activity 和 Fragments,有几个选项,但经过大量阅读和许多经验后,我发现它可以通过这种方式恢复:

  • Activity 想和孩子沟通 Fragment =>只需在您的网站上编写公共方法 Fragment 上课,然后让 Activity 给他们打电话
  • Fragment 想与父母沟通 Activity =>这需要更多的工作,作为官方的Android链接 https://developer.android.com/training/basics/fragments/communicating 建议,定义一个是一个好主意 interface 这将由实施 Activity,谁将与任何人建立合同 Activity 想要与之沟通 Fragment。例如,如果你有 FragmentA,谁愿意与任何人沟通 activity 包括它,然后定义 FragmentAInterface 这将定义什么方法可以 FragmentA 呼唤 activities 决定使用它。
  • 一个 Fragment 想与其他人沟通 Fragment =>这是您遇到最“复杂”情况的情况。由于您可能需要将数据从FragmentA传递到FragmentB,反之亦然,这可能导致我们定义2个接口, FragmentAInterface 这将由实施 FragmentB 和 FragmentAInterface 这将由实施 FragmentA。这将开始使事情变得混乱。想象一下,如果你还有更多 Fragment现场,甚至父母 activity 想与他们沟通。那么,这个案例是建立共享的完美时刻 ViewModel为了 activity 而它是 fragment秒。更多信息在这里 https://developer.android.com/topic/libraries/architecture/viewmodel 。基本上,你需要定义一个 SharedViewModel class,包含您要在之间共享的所有数据 activity 和 fragments 需要在它们之间传递数据。

ViewModel case,最后使事情变得更简单,因为你不必添加额外的逻辑,使代码中的东西变脏并且凌乱。此外,它还允许您将数据的收集(通过调用SQLite数据库或API)分开 Controller (activities 和 fragments)。


0