繁体   English   中英

正确地保留听众的方向变化

[英]Correctly retaining listeners on orientation changes

请考虑以下情形:

  1. 我有一个带有UI元素的Activity ,单击时会启动DialogFragment
  2. DialogFragment有一个侦听器interfaceActivity提供了一个实现。 比如说, Activity是一个图像编辑器, DialogFragment选择一个对比 - 该对话框将有一个OnContrastChangedListener ,该Activity实现
  3. Activity已实现此interface以在其UI中更新视图。 继续使用图像编辑器示例, Activity实现了OnContrastChangedListener来更新其预览视图 - 如下所示:

     contrastDialog.setOnContrastChangedListener(new OnContrastChangedListener { @Override public void OnContrastChanged(int newContrast) { getPreviewView().updateWithContrast(newContrast); } }); 
  4. 方向已更改,所有内容都将重新创建,并且使用此处推荐的方法正确保存和恢复侦听器(侦听器保存在Fragment并在生命周期恢复状态时恢复)。

问题是监听器接口现在不起作用 函数getPreviewView()现在返回null即使在Activity其他任何地方调用它时它返回正确的值

请原谅可怜的术语(我在编译和字节码方面的知识有限),但我能掌握所发生的事情。 该接口已使用getPreviewView()版本进行编译,该版本返回了在方向更改时销毁的预览视图,此后已发布/垃圾收集/现在为null

我的问题是,在Java中是否有一种方法可以使接口编译期望值/函数发生变化 - 就像C中的volatile关键字(我期待没有)? 在这种情况下,解决这种情况的最佳方法是什么? 我考虑过以下几点:

  • 在重新创建 Activity时重新运行的代码中创建 DialogFragment (及其 interface )。 这对于 OnClickListeners for Buttons这样的东西 OnClickListeners ,因为它们肯定是创建的。 但是这个 DialogFragment仅在按下按钮时创建,因此这种方法意味着每次 Activity时都会创建屏幕的每个对话框 - 这看起来很浪费,因为它们甚至可能无法运行
  • 每次为 Activity创建所有可能的 interfaces并将它们保存在成员变量中,然后在请求由事件创建 DialogFragments时使用这些 interfaces 与上面相同的评论 - 似乎浪费创建每个可能的 interface ,以防它运行。
  • 在Activity中保留一些hacky“open dialog state”成员变量来指导interfaces的重新创建。 Hacky并在ActivityDialogFragment之间创建了一个平局,这不是很好的做法。

如您所见,所有选项都涉及在某种程度上浪费的娱乐 - 有没有办法重用现有的interface实现?

编辑:选项1和2不起作用,因为它们需要指向现有Dialog的链接。 这一切都是可行的但它越来越倾向于使用“当前Dialog”变量的黑客共同选项,在重新启动活动时使用FragmentManager获取DialogFragment ,根据“当前Dialog”变量适当地转换它,重新创建监听器。 有一种不那么混乱的方式吗?

onAttach onDetach方法很好,我喜欢使用它,有时,当我知道代码中会有更多的开发人员我甚至不会盲目地使用它,但我做了这样的检查:

if(activity instanceof MyInterface){
   interface = (MyInterface) activity;
} else{
   thrown new RuntimeException("Dear colleague, this fragment was meant to have the activity implementing MyInterface or else a bunch of other stuff won't work, please go back to your code and add the interface");
}

但作为一种不同的手段,您还可以在重新创建片段时重新设置界面。 例如,关于onCreate的活动

if(savedInstanceState != null){
    mDialogFrag = getSupportFragmentManager().findFragmentByTag(MyDialogFrag.TAG);
    if(mDialogFrag != null)
       mDialogFrag.setListener(... the interface   ...);
}

我知道这也不是对象的最佳分离,但事实是getPreviewView()需要当前活动才能正常运行,因此当你重建所有人时,你需要再次传递这个引用。

这些只是不同的方式。

如果活动将始终具有接口的实现,是否可以在DialogFragment的onAttach()中设置监听器? 这将确保在销毁和重新创建时,它将具有最新的参考,例如:

public void onAttach(Activity activity) {
    super.onAttach(activity);
    contrastChangedListener = (OnContrastChangedListener)activity;
}

public void onDetach() {
    super.onDetach();
    contrastChangedListener = null;

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM