Android Fragments基本原理:为什么?这在概念上是错的吗?

Fra*_*coC 13 android communication interface fragment

我对Android中的"正确编程"有疑问.

我目前正在使用片段开发应用程序.它涉及动态添加的片段到Activity,从XML膨胀的片段,从XML嵌套的片段或动态添加.让我们说一点,一切.

这个问题关注的概念是与片段有关的沟通过程.所以,我已经阅读了文档,这不是我第一次尝试使用片段.

常识(和文档)告诉我们,如果Fragment想要说话或与其活动进行交流,我们应该使用一个界面.

例:

TestFragment

public class TestFragment extends Fragment {

  private TestFragmentInterface listener; 

  public interface TestFragmentInterface {

      void actionMethod();

  }


  @Override
  public void onViewCreated(View view, Bundle savedInstanceState) {

      if (getActivity() instanceof TestFragmentInterface) {
          listener = (TestFragmentInterface) getActivity();
      }

      // sending the event
      if (listener != null) listener.actionMethod();
  }

}
Run Code Online (Sandbox Code Playgroud)

测试活动

public class Test implements TestFragmentInterface {

  @Override
  public void actionMethod() {
    ..
  }
}
Run Code Online (Sandbox Code Playgroud)

这里一切都很好.

这提高了可重用性,因为我的TestFragment可以与任何类型的Activity交互,因为Activity实现了我声明的接口.

反过来说,Activity可以通过保持引用并调用其公共方法来与片段交互.这也是使用Activity作为桥接器进行片段到片段通信的建议方法.

这很酷,但有时感觉就像使用接口这只是有点"太多".

问题A.

在这个场景中,我附加的片段具有非常集中的角色,这意味着它们是针对该特定活动完成的,否则不会被使用,忽略接口实现在概念上是错误的,只是做了类似的事情.

((TestActivity) getActivity().myCustomMethod();
Run Code Online (Sandbox Code Playgroud)

这也适用于这样的场景(不是我的情况,只是把它当作"最坏的")我的活动必须处理各种各样的这些不同的片段,这意味着它应该为它应该处理的每个片段实现一个方法.这使代码陷入了一堆"可能不需要的线".

继续前进:仍然使用"聚焦"片段,旨在仅在某种方式下工作,使用嵌套片段是什么?

添加它们就像

public class TestFragment extends Fragment {


  private void myTestMethod() {

    NestedFragment nested = new NestedFragment();

    getChildFragmentManager()
      .beginTransaction()
      .add(R.id.container, nested)
      .commit();
  }

}
Run Code Online (Sandbox Code Playgroud)

这将NestedFragment绑定到TestFragment.我再说一遍,NestedFragment,就像TestFragment一样,只能以这种方式使用,否则没有任何意义.

回到问题,我应该如何处理这种情况?

问题B

1)我应该在NestedFragment中提供一个接口,并使TestFragments实现NestedFragmentInterface吗?在这种情况下,我将采取以下行动

NestedFragment

public class NestedFragment extends Fragment {

  private NestedFragmentInterface listener; 

  public interface NestedFragmentInterface {

      void actionMethodNested();

  }


  @Override
  public void onViewCreated(View view, Bundle savedInstanceState) {

      if (getParentFragment() instanceof NestedFragmentInterface) {
          listener = (NestedFragmentInterface) getParentFragment();
      }

      // sending the event
      if (listener != null) listener.actionMethodNested();
  }

}
Run Code Online (Sandbox Code Playgroud)

2)应该(或可以)忽略接口,然后调用

getParentFragment().publicParentMethod();
Run Code Online (Sandbox Code Playgroud)

3)我应该在NestedFragment中创建接口,但让活动实现它,以便活动将调用TestFragment?

问题C.

关于使用Activity作为片段之间的桥梁的想法,我相信它是为了正确处理所有这些对象的生命周期.在尝试手动处理系统可能引发的异常时,是否仍然可以进行直接片段到片段(使用接口或直接调用公共方法)?

nbr*_*ing 10

我尽力回答这里的文字墙:)

问题A:

片段设计为可重复使用的模块,可以插入和播放任何活动.因此,与活动交互的唯一正确方法是让活动从片段理解的接口继承.

public class MapFragment extends Fragment {

  private MapFragmentInterface listener; 

  public interface MapFragmentInterface {

      //All methods to interface with an activity

  }


  @Override
  public void onViewCreated(View view, Bundle savedInstanceState) {
      // sending the event
      if (listener != null) listener.anyMethodInTheAboveInterface();
  }

}
Run Code Online (Sandbox Code Playgroud)

然后让活动实现接口

public class MainActivity extends Activity implement MapFragmentInterface{

//All methods need to be implemented here
}
Run Code Online (Sandbox Code Playgroud)

只要活动实现此接口,这允许您的片段与任何活动一起使用.您需要此接口的原因是因为片段可以与任何活动一起使用.调用类似的方法

((TestActivity) getActivity().myCustomMethod();
Run Code Online (Sandbox Code Playgroud)

依赖于这样一个事实,即您的片段只能在测试活动中工作,因此会"破坏"片段的规则.

问题B和C:

假设您遵循正确的片段准则并且它们是独立的模块.那么你应该永远不会有片段需要彼此了解的情况.99%的时间人们认为他们需要片段来直接沟通,他们可以通过使用MVC模式或类似的东西将他们的问题重新考虑到我上面给出的情况.让活动像控制器一样,在需要更新时告诉碎片,然后创建一个单独的数据存储.


bus*_*lee 4

我会试着把这一切都弄清楚一点。

首先,考虑为片段设置侦听器的方法。在 onViewCreated 方法中设置侦听器是没有好处的,因为它会导致在创建任何片段时过度重置侦听器。将其设置到 onAttach 方法中就足够了。

我讲述了代码行。请注意,让 BaseFragment 在您的应用程序中实现常见行为(如设置 FragmentListener 从资源创建视图)是件好事。

不仅如此,为了减少代码行并获得部分代码重用,您可以在 BaseFragment 中使用泛型。那么看看下一个代码片段:

public abstract BaseFragment<T extends BaseFragmentListener> extends Fragment {

  T mListener;

  public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (Activity instanceof T)
      mListener = (T) activity; 
  }

  abstract int getLayoutResourceId();

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View layout = inflater.inflate(getLayoutResourceId(), null);
        // you can use some view injected tools here, mb ButterKnife 
        return layout;
    }
}
Run Code Online (Sandbox Code Playgroud)

答案A(针对问题A):

如果您只有一个 Activity 的 Fragment,您需要决定:“您真的需要在这里使用 Fragment 吗?”。但是mb最好有一个活动的片段,以便从活动中提取一些视图逻辑并清除基本逻辑。但为了清除应用程序的基本架构逻辑,请使用监听器。这将使其他开发人员的生活更轻松

答案 B:对于嵌套片段,您需要解决什么问题,他们需要使用精确的活动还是仅使用片段并将其用作与其他系统的桥梁。如果您知道嵌套片段将一直嵌套,则需要将父片段声明为侦听器,否则您必须使用其他方法。

注意:作为应用程序不同部分之间通信的基本方法,您可以使用事件,也可以尝试查看事件总线。它为您提供了通用的通信方法,您可以提取调用侦听器的自定义方法的逻辑以及更多其他逻辑,所有逻辑都将位于处理事件中,并且您将拥有一个用于合作的中介系统。

答案C:我部分解释了片段之间合作的方法之一。使用一个事件调度程序可以避免为所有不同的通信拥有多个侦听器。有时它是非常有利可图的。

或者我认为使用 Activity 或 Activity 中的其他类作为 Fragment 协作的中介更有用,因为在处理和系统生命周期中 Fragments 发生变化的情况很多。它将所有这些逻辑集中在一个地方,并使您的代码更加清晰。

希望我的考虑对你有帮助。