【问题标题】:Android Activity interfaces to Fragments: try/catch blocks vs. instanceof checksAndroid Activity 与 Fragments 的接口:try/catch 块与 instanceof 检查
【发布时间】:2023-03-12 18:35:01
【问题描述】:

在 Google 的article on communicating with Fragments 中,作者给出了以下示例来检查片段的调用活动是否实现了所需的接口:

try {
    mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
    throw new ClassCastException(activity.toString()
        + " must implement OnHeadlineSelectedListener");
}

通常,我更喜欢显式检查而不是 try/catch 块。在这种情况下,我认为以下示例更可取:

if (activity instanceof OnHeadlineSelectedListener) {
    mCallback = (OnHeadlineSelectedListener) activity;
} else {
    throw new ClassCastException(activity.toString()
        + " must implement OnHeadlineSelectedListener");
}

是否有理由更喜欢一种检查策略而不是另一种?在定义 Fragments 的接口时是否应该使用另一种策略?

【问题讨论】:

  • 您可以只进行裸转换,既没有 instanceof 也没有 try/catch,并相信转换正常抛出的异常将包含您需要的信息。
  • 我同意这个检查似乎不是绝对必要的,但谷歌推荐它,所以我很好奇他们的模式是否有特别的优势。
  • 我个人不使用这样的检查,因为如果我编写好的代码,那么这个错误将永远不会发生。 try{}catch{} 选项的一个可能原因是在 catch 块中抛出异常比在 else 中更有意义。但实际上,无论如何,抛出异常是处理生产错误的错误方法。
  • 从不,但从不,使用异常作为控制程序流的一种方式。这是糟糕的设计,并且会产生无法维护的意大利面条式代码。
  • 查看this question 和相关的。如果它实现了接口,那么它必须实现方法。

标签: java android android-fragments


【解决方案1】:

是否有理由更喜欢一种检查策略而不是另一种?

主要是个人喜好。 instanceof 对于阅读您的代码的人来说更明确。 try{}catch{} 在功能上做同样的事情

定义接口时是否应该使用另一种策略 到片段?

我不知道。

进一步的解释:(因为我觉得漫无目的)

这不应该是一个“意外”的问题。如果您编写好代码,则永远不必担心该错误。(忽略这一点,以回应OP的评论)

另外值得一提的是,Google 推荐的抛出新错误的方法会添加不必要的代码,因为默认异常将包含您需要的信息。此外,抛出错误会导致糟糕的用户体验。

任何一个选项对性能的影响都可以忽略不计(除非您正在做一些不合理的事情,例如循环和检查数千次),因此(在性能方面)您可以使用适合您首选编码风格的任何一个。

我的猜测是 Google 推荐使用 try{} catch{} 选项,因为从 catch 块中抛出异常比从 else 中抛出异常更有意义。大概也是因为那篇文章的作者个人比较喜欢try{}catch{}的风格吧。

从功能上讲,这两种方法都做同样的事情。 instanceof 检查的含义更明确,因为代码清楚地说明了您要检查的内容,如果您必须进行检查,我建议您使用 instanceof 方法。

【讨论】:

  • 我对处理这个问题的兴趣源于片段库中的片段,这些片段由可能无法访问片段源的多个开发人员共享。我希望能够清楚地传达他们可能遇到的问题的原因。
【解决方案2】:

通常,我更喜欢 instanceof 方法,因为抛出和捕获异常被认为是昂贵的。 另外,我认为实例方法更具可读性。

【讨论】:

    【解决方案3】:

    请参阅我之前的两个答案,了解我如何处理这两个问题:

    片段(https://stackoverflow.com/a/27716730/950427):

    public MyAdapter(Fragment fragment) {
        try {
            this.mAdapterCallback = ((AdapterCallback) fragment);
        } catch (ClassCastException e) {
            throw new ClassCastException("Fragment must implement AdapterCallback.");
        }
    }
    

    活动(https://stackoverflow.com/a/27716788/950427):

    public MyAdapter(Context context) {
        try {
            this.mAdapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.");
        }
    }
    

    需要上下文的片段的特殊情况:

    private Activity activity;
    
    public MyAdapter(Fragment fragment) {
        this.fragment = fragment.getActivity(); // use as Context
        try {
            this.mAdapterCallback = ((AdapterCallback) fragment);
        } catch (ClassCastException e) {
            throw new ClassCastException("Fragment must implement AdapterCallback.");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      相关资源
      最近更新 更多