{"record":{"id":"450a5aac96aa53ee","repo":"material-components/material-components-android","slug":"demo-must-implement-createfragment-or-createactivi","errorCode":null,"errorMessage":"Demo must implement createFragment or createActivityIntent","messagePattern":"Demo must implement createFragment or createActivityIntent","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"catalog/java/io/material/catalog/feature/Demo.java","lineNumber":66,"sourceCode":"  }\n\n  @Nullable\n  public Intent createActivityIntent() {\n    return null;\n  }\n\n  @NonNull\n  public String getDemoClassName() {\n    Fragment fragment = createFragment();\n    if (fragment != null) {\n      return fragment.getClass().getSimpleName();\n    }\n    Intent activityIntent = createActivityIntent();\n    if (activityIntent != null) {\n      String className = activityIntent.getComponent().getClassName();\n      return className.substring(className.lastIndexOf('.') + 1);\n    }\n    throw new IllegalStateException(\"Demo must implement createFragment or createActivityIntent\");\n  }\n}\n","sourceCodeStart":48,"sourceCodeEnd":69,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/catalog/java/io/material/catalog/feature/Demo.java#L48-L69","documentation":"Demo.getDemoClassName() derives the demo's class name by first trying createFragment(), then createActivityIntent(). If a Demo subclass overrides neither (both return null by default), the method has no name to report and throws IllegalStateException. Every Demo must implement at least one of these factory methods.","triggerScenarios":"Defining a Demo (or DemoLandingFragment Demo) subclass that overrides neither createFragment() nor createActivityIntent(), then the catalog calls getDemoClassName() on it (e.g. while building the demo list UI or logging analytics).","commonSituations":"Adding a new demo entry and forgetting to implement its factory method; refactoring a demo from a Fragment to an Activity and accidentally deleting both overrides; a Demo subclass whose createFragment() returns null because the fragment field was never set.","solutions":["Override createFragment() in your Demo subclass to return your demo Fragment instance.","If the demo is an Activity instead, override createActivityIntent() to return a non-null Intent for it.","Ensure the override actually returns a non-null object in every code path (no conditional null returns)."],"exampleFix":"// before\nclass MyDemo extends Demo {\n  // no factory method overridden -> IllegalStateException\n}\n\n// after\nclass MyDemo extends Demo {\n  @Override\n  public Fragment createFragment() {\n    return new MyDemoFragment();\n  }\n}","handlingStrategy":"validation","validationCode":"boolean valid = demo.createFragment() != null || demo.createActivityIntent() != null;\nif (!valid) {\n  throw new ConfigurationError(demo.getClass().getName() + \" implements no factory method\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make Demo abstract with required factories, or use a base class that forces one override.","Add a startup assertion over the demo list so misconfigured demos fail during development, not at navigation time."],"tags":["catalog-demo","lifecycle","illegal-state","configuration"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}