Direct answer
An Activity recreation caused by rotation, locale change, or window resizing creates a new screen instance; it does not mean the user's inference request should be started again. Android documentation recommends keeping business state in a suitable state holder such as a ViewModel and restoring only small UI state separately. For local AI, the critical design question is ownership: the screen renders a task, while a longer-lived application or feature coordinator owns the operation and its native resources. If the screen itself owns the engine or coroutine, disposal can close work the user still expects to finish. If the new screen blindly repeats the submit action, the model may receive the same request twice. Make task identity explicit before testing. Give each user action a stable operation ID and store a bounded state record such as queued, running, partial, succeeded, failed, or cancelled. The record should contain references to durable results and progress metadata, not a native pointer, camera object, Activity, large media buffer, or an assumption that a process will stay alive. On recreation, the new screen observes the existing operation and renders its current status. It must not call inference again simply because its first composition ran. A ViewModel can survive configuration recreation, but that fact is not a guarantee of process survival; durable recovery is a separate test. Test the boundary under controlled conditions. Start a prompt or image task, force Activity recreation while it is queued, during streaming, after partial output, and after completion but before navigation. Rotate the device and resize a multi-window window; also change locale if that is part of the app's supported configuration. Count engine submissions by operation ID, observe cancellation and close events, and verify that the replacement screen attaches to the same result stream or persisted record. Keep this separate from process-death testing: a configuration-change test expects a new Activity in the same process, whereas process loss requires rebuilding native state from durable data. The user contract should decide what happens if the task cannot survive the screen transition. If cancellation is intentional, the UI should show a cancelled state and allow a deliberate new request. If the operation is application-owned, screen disposal should remove observers rather than close the runtime. If a task is interrupted by process death, do not claim it continued: restore the last committed state, mark uncertain output incomplete, and offer an explicit retry. Never save a raw native handle into SavedStateHandle or a Bundle; those mechanisms are for serializable UI state, not engine ownership. Use evidence that can catch both duplicate work and hidden resource leaks. Record the operation ID, lifecycle transition, submission count, terminal state, persisted-result version, and whether the native owner was closed. Exclude user prompt and media bytes from ordinary diagnostic logs. The project fact card supports testing explicit model lifecycle transitions but does not prove that every Cove screen is already recreation-safe. The guide therefore gives a verification method, not a product claim. A passing test is bounded to the tested app build, screen, task type, Android configuration, and recovery path; it does not prove process-death recovery or all-device compatibility.
Rotation while a local summarization request is streaming
A user submits a long note for local summarization and rotates the phone while partial output is visible. The Activity is recreated, while the request coordinator and model runtime may still be active in the process.
Decision
Keep one operation ID and one task owner; let the replacement screen observe existing progress and never infer again merely because composition restarted.
Expected outcome
The user sees one coherent result, partial output is not duplicated, and the screen lifecycle does not prematurely close the shared runtime.
Evidence to collect
The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:
- Task and UI ownership map
- Rotation fixtures by task state
- Single execution and restored result assertions
A runtime comparison is publishable only when artifact identity, build configuration, selected backend, task fixture, and failures are recorded.
Implementation workflow
- Separate screen state from operation ownership. Draw a boundary between transient UI state, durable task state, and runtime resources. The screen may own scroll position and selected tab; a longer-lived coordinator owns task identity, cancellation policy, and engine lifetime.
- Define one stable operation identity. Create an operation ID at the user action boundary. Store explicit state and result references so a newly created screen can attach to the existing operation rather than treating recomposition as a new submission.
- Exercise recreation at meaningful states. Trigger rotation or resize while queued, running, streaming partial output, and after success. Include a locale change only if the application handles that configuration; count model submissions for each operation ID.
- Assert observer and owner behavior. Verify that the old screen stops collecting and releases only screen-scoped resources. Verify the new screen observes the same task and that Activity disposal does not close a runtime owned outside that Activity.
- Keep process death as a separate scenario. Run a different test that kills the process and reconstructs from durable state. Mark uncommitted output incomplete and do not claim that an in-memory ViewModel or native session survived.
Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.
Acceptance criteria
- A single user action maps to one operation ID and no duplicate inference submission occurs after a configuration recreation.
- The recreated screen displays the correct queued, running, partial, terminal, or cancelled state without holding the old Activity.
- Screen disposal removes observers but closes only resources owned by that screen; shared runtime close behavior is asserted separately.
- Configuration recreation and process death are reported as different test cases with different recovery expectations.
Decision table
| Dimension | Choice or evidence | How to interpret it |
|---|---|---|
| Configuration recreation in same process | Reconnect to the existing operation owner | New Activity instance; native state may still exist but must not be duplicated or screen-owned. |
| Process death and relaunch | Rebuild from durable state or mark interrupted | In-memory task and native handles are gone; this needs a separate recovery contract. |
| User explicitly cancels | Cancel once and show a terminal cancelled state | A deliberate product transition, not an incidental screen disposal side effect. |
Failure patterns to prevent
- Starting duplicate inference after rotation
- Closing shared runtime from screen disposal
Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.
Minimum reproducibility record
| Layer | Record |
|---|---|
| Device | Manufacturer, model, chipset, RAM class, operating-system build |
| Software | Application version and git commit |
| Model | Family, variant, revision, format, file length, hash, quantization |
| Runtime | Name, revision, requested backend, observed backend evidence |
| Workload | Fixture revision, input hash, prompt hash, output policy |
| Outcome | Completed, failed, cancelled, fallback, and privacy-safe diagnostics |
Release checklist
- ☐ The primary query is answered without an unsupported number.
- ☐ Every artifact and runtime is pinned.
- ☐ The representative task and failure policy are explicit.
- ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
- ☐ User-content and network boundaries are documented.
- ☐ Result wording applies only to the recorded configuration.
- ☐ The page links to raw method or evidence when results are added.
Sources and related evidence
- Android persistent background work
- Android activity state changes and configuration recreation
- Save UI state in Jetpack Compose
Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.
Frequently asked questions
Should rotation restart an in-progress model request?
Usually no. The new screen should observe the existing operation ID. Restart only when the product explicitly defines cancellation and the user initiates a new request.
Does a ViewModel guarantee that inference survives every restart?
No. A ViewModel helps retain business state across configuration recreation, but process death removes in-memory native state. Durable recovery needs its own design and test.
Can a native engine handle be saved in instance state?
No. Save small serializable UI data or stable IDs. Native handles need a live owner and must be recreated after process loss, not serialized into a Bundle.