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

时间:2014-10-04 04:16:03

标签: java android android-fragments interface android-orientation

考虑以下情况:

  1. 我有Activity个UI元素,点击时会启动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. 更改方向,重新创建所有内容,并使用建议的方法here正确保存和恢复侦听器(侦听器保存在Fragment中,并在生命周期恢复状态时恢复)。

  5. 问题是现在的监听器界面。函数getPreviewView()现在返回null,即使在Activity中的任何其他位置调用它时它返回正确的值

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

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

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

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

    编辑:选项1和2无效,因为他们需要指向现有Dialog的链接。这一切都是可行的,但它越来越倾向于使用“当前对话框”变量的黑客共同选项,在重新启动活动时将DialogFragmentFragmentManager一起使用,根据'当前的Dialog'变量,重新创建监听器。是否有一种不那么混乱的方式?

2 个答案:

答案 0 :(得分:1)

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()需要当前活动才能正常运行,因此当每个人都被重建时,你需要再次传递这个引用。

这些只是不同的方式。

答案 1 :(得分:0)

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

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

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

}