Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在方向更改时正确保留侦听器_Java_Android_Android Fragments_Interface_Android Orientation - Fatal编程技术网

Java 在方向更改时正确保留侦听器

Java 在方向更改时正确保留侦听器,java,android,android-fragments,interface,android-orientation,Java,Android,Android Fragments,Interface,Android Orientation,考虑以下场景: 我有一个带有UI元素的活动,单击时会启动一个对话框片段 对话框片段有一个监听器接口,活动提供了该接口的实现。例如,活动是一个图像编辑器,对话框片段选择一个对比度-该对话框将有一个活动实现的OnContastChangedListener 活动已实现此界面,以更新其UI中的视图。继续图像编辑器示例,活动实现了OnContrast ChangedListener以更新其预览视图,如下所示: contrastDialog.setOnContrastChangedListener(new

考虑以下场景:

  • 我有一个带有UI元素的
    活动
    ,单击时会启动一个
    对话框片段
  • 对话框片段
    有一个监听器
    接口
    活动
    提供了该接口的实现。例如,
    活动
    是一个图像编辑器,
    对话框片段
    选择一个对比度-该对话框将有一个
    活动
    实现的
    OnContastChangedListener
  • 活动
    已实现此
    界面
    ,以更新其UI中的视图。继续图像编辑器示例,
    活动
    实现了
    OnContrast ChangedListener
    以更新其预览视图,如下所示:

    contrastDialog.setOnContrastChangedListener(new OnContrastChangedListener {
        @Override
        public void OnContrastChanged(int newContrast) {
            getPreviewView().updateWithContrast(newContrast);            
        }
    });
    
    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");
    }
    
  • 更改方向,重新创建所有内容,并使用建议的方法正确保存和还原侦听器(侦听器保存在
    片段中,并在生命周期处于还原状态时还原)

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

    请原谅这个糟糕的术语(我在编译和字节码方面的知识是有限的),但我能理解发生了什么。该接口已使用
    getPreviewView()
    版本编译,该版本返回了在方向更改时被破坏的预览视图,并且该视图已被发布/垃圾回收/现在为
    null

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

    • 在重新创建
      活动
      时重新运行的代码中创建
      对话框片段
      (及其
      接口
      )。这对于
      OnClickListeners
      for
      按钮
      这样的东西很好,因为它们是绝对创建的。但是这个
      对话框片段
      仅在按下按钮时创建,因此这种方法意味着每次
      活动
      启动时都会创建屏幕上的每个对话框,这似乎是浪费,因为它们甚至可能不会运行
    • 每次为
      活动
      创建所有可能的
      接口
      ,并将其保存在成员变量中,然后在事件请求创建
      对话框片段
      时使用这些
      接口。与上面的注释相同-创建每一个可能的
      接口
      似乎是浪费,以防它运行
    • 在活动中保留一些粗糙的“打开对话框状态”成员变量,用于指导
      界面的重新创建。Hacky并在
      活动
      对话框片段
      之间建立了联系,这不是一个很好的实践
    正如您所看到的,所有的选项都涉及到某种程度上的浪费——有没有办法重用现有的
    接口
    实现


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

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

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

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

    contrastDialog.setOnContrastChangedListener(new OnContrastChangedListener {
        @Override
        public void OnContrastChanged(int newContrast) {
            getPreviewView().updateWithContrast(newContrast);            
        }
    });
    
    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()
    需要当前活动才能正常运行,因此当所有人都被破坏或重建时,您需要再次传递此引用


    这些只是不同的方法。

    哪里是
    getPreviewView()
    implement?你能告诉我们这个方法吗?@Code学徒:这只是一个例子。例如,它的实现可以是
    return(PreviewView)findviewbyd(R.id.preview)
    其中
    PreviewView
    是一个自定义视图类,
    R.id.preview
    是在XML布局中定义的id,这基本上只是选项2(看起来最有可能)。但是,这个答案不起作用有几个原因(将活动投射到侦听器:假设活动实现是一个错误的假设,如果另一个片段实现了侦听器会发生什么?)