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

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

屏幕截图

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

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

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

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

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

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

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

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

Simple Developer Blog上有一个关于如何做到这一点的好教程。

我希望这对你有所帮助!

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

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

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

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

它是通过回调接口实现的:首先我们要创建一个接口:

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...... } }); 

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

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

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

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

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

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

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

  • Activity想要与子进行通信Fragment =>只需在Fragment类中编写公共方法,然后让Activity调用它们
  • Fragment想要与父亲进行交流Activity =>这需要更多的工作,正如官方的Android链接https://developer.android.com/training/basics/fragments/communicating所示,定义一个好主意一个将由Activity实现的interface ,它将为任何想要与该Fragment通信的Activity建立合同。 例如,如果你想要与任何包含它的activity进行通信的FragmentAInterface ,那么定义FragmentAInterface ,它将定义FragmentA可以为决定使用它的activities调用什么方法。
  • Fragment想要与其他Fragment进行通信=>这是您遇到最“复杂”情况的情况。 由于您可能需要将数据从FragmentA传递到FragmentB,反之亦然,这可能导致我们定义2个接口, FragmentAInterface将由FragmentB实现, FragmentA将由FragmentA实现。 这将开始使事情变得混乱。 想象一下,如果你有更多的Fragment ,甚至父activity想与他们沟通。 好吧,这个案例是为activityfragment s建立共享ViewModel的完美时刻。 更多信息请访问https://developer.android.com/topic/libraries/architecture/viewmodel 。 基本上,您需要定义一个SharedViewModel类,该类包含您希望在activity和需要在它们之间传递数据的fragments之间共享的所有数据。

ViewModel情况最终使事情变得更加简单,因为您不必添加额外的逻辑,这会使代码中的内容变得肮脏并且变得混乱。 此外,它还允许您将来自Controlleractivitiesfragments )的数据收集(通过调用SQLite数据库或API)分开。

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

我正在使用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);