{"record":{"id":"756e256ddd0c38ce","repo":"airbnb/epoxy","slug":"diffing-is-enabled-you-should-use-notifymodelschanged","errorCode":null,"errorMessage":"Diffing is enabled. You should use notifyModelsChanged instead of notifyDataSetChanged","messagePattern":"Diffing is enabled\\. You should use notifyModelsChanged instead of notifyDataSetChanged","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java","lineNumber":36,"sourceCode":"  // Using a HashMap instead of a LongSparseArray to\n  // have faster look up times at the expense of memory\n  private Map<Long, ModelState> oldStateMap = new HashMap<>();\n  private ArrayList<ModelState> currentStateList = new ArrayList<>();\n  private Map<Long, ModelState> currentStateMap = new HashMap<>();\n  private final BaseEpoxyAdapter adapter;\n  private final boolean immutableModels;\n\n\n  DiffHelper(BaseEpoxyAdapter adapter, boolean immutableModels) {\n    this.adapter = adapter;\n    this.immutableModels = immutableModels;\n    adapter.registerAdapterDataObserver(observer);\n  }\n\n  private final RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() {\n    @Override\n    public void onChanged() {\n      throw new UnsupportedOperationException(\n          \"Diffing is enabled. You should use notifyModelsChanged instead of notifyDataSetChanged\");\n    }\n\n    @Override\n    public void onItemRangeChanged(int positionStart, int itemCount) {\n      for (int i = positionStart; i < positionStart + itemCount; i++) {\n        currentStateList.get(i).hashCode = adapter.getCurrentModels().get(i).hashCode();\n      }\n    }\n\n    @Override\n    public void onItemRangeInserted(int positionStart, int itemCount) {\n      if (itemCount == 0) {\n        // no-op\n        return;\n      }\n\n      if (itemCount == 1 || positionStart == currentStateList.size()) {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java#L18-L54","documentation":"When diffing is enabled, DiffHelper registers an AdapterDataObserver whose onChanged() throws UnsupportedOperationException. This catches calls to notifyDataSetChanged(), which would wipe RecyclerView's animation state and defeat the purpose of diffing. You must use notifyModelsChanged() instead, which runs the diff and emits granular notifications.","triggerScenarios":"Calling adapter.notifyDataSetChanged() (directly or via RecyclerView helpers) on an EpoxyAdapter that has called enableDiffing().","commonSituations":"Copy-pasted RecyclerView code calling notifyDataSetChanged() after setModels(); Paging or SwipeRefresh callbacks that blanket-notify; upgrading from a non-diffing adapter to enableDiffing() without removing legacy notifyDataSetChanged calls.","solutions":["Replace notifyDataSetChanged() with notifyModelsChanged() on the EpoxyAdapter","Remove or gate any framework/library code paths that call notifyDataSetChanged()","Call notifyItemChanged/Inserted/Removed for single-item updates instead","If blanket notification is truly needed, do not enable diffing on that adapter"],"exampleFix":"// before\nadapter.notifyDataSetChanged();\n\n// after\nadapter.notifyModelsChanged();","handlingStrategy":"validation","validationCode":"// avoid the throwing call when diffing is on\nif (!adapter.isDiffingEnabled()) { adapter.notifyDataSetChanged(); } else { adapter.notifyModelsChanged(); }","typeGuard":null,"tryCatchPattern":"// if third-party code may call it\ntry {\n  adapter.notifyDataSetChanged();\n} catch (UnsupportedOperationException e) {\n  adapter.notifyModelsChanged();\n}","preventionTips":["Standardize on notifyModelsChanged() in codebases with diffing adapters","Grep for notifyDataSetChanged in diffing-enabled screens","Wrap legacy notification helpers behind one adapter-facing API"],"tags":["android","epoxy","diffing","recyclerview"],"backgroundTag":"unsupported-operation","analyzedSha":"e45bd3a61fe3a1f130e184f5b8dcf172ab99025a","analyzedAt":"2026-09-13T03:24:16.052Z","contentChangedAt":"2026-09-13T03:24:16.052Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}