Mobile Application Concepts
By the end of this lesson
Explain how device constraints change application design.
A mobile application is code that runs on a device the user carries, under an operating system that treats your app as a guest. The operating system decides how much memory you keep, how often you may run in the background, and whether you continue to exist at all when the user switches to something else.
That is the single biggest shift from server or browser work, and everything else in this course follows from it. You are not in charge of your own process, the network is a courtesy rather than a guarantee, and every pixel and every milliamp is contested.
The example running through this course is a companion app for field staff. Engineers visit sites, look up a colleague's details, and record notes about the visit. Behind it is the employees API taught elsewhere in the Academy — the same endpoints, reached from a device that spends part of its day in a basement with no signal.
Plenty of things differ between a phone and a laptop. These six genuinely change the design, and they change decisions you make on day one, which is why they are worth naming before any code:
- Intermittent and slow connectivity
- A device moves. It loses signal in lifts, car parks and plant rooms, and it regains it halfway through a request. Worse than no signal is a connection that accepts your request and then delivers nothing — you get a hang rather than an error. Design for a network that is sometimes absent and often slow, not one that is usually fine.
- Battery
- Radio use, GPS and waking the screen all cost measurable power. A polling loop that runs every ten seconds is invisible on a server and noticeable on a phone by mid-afternoon. Users uninstall apps that flatten their battery, and the operating system will throttle you before they do.
- Limited screen area
- You have room for one thing at a time. A desktop layout shows a list, a detail panel and a filter sidebar together; a phone shows one of them and navigation to the others. That is a structural decision about screens and flow, not a styling problem to solve at the end.
- Touch instead of a pointer
- A mouse cursor is one pixel with a visible position. A fingertip covers a patch several millimetres across, arrives without a hover state, and hides what it is touching. Controls that work with a mouse are frequently unusable with a thumb.
- The operating system suspends and terminates your app
- When the user leaves your app, it moves to the background, then usually stops running, and may be terminated outright so its memory can go to whatever is in the foreground. This is normal behaviour, not a failure, and it happens to every app. Anything held only in memory is gone.
- Store review stands between you and your users
- A release goes to a review queue before it reaches anybody, and can be rejected. Users then choose whether to update, so several versions of your app talk to your API at once. A fix is days away rather than minutes, and old clients stay in the field for months.
If you have built for the web, the honest contrast is useful. Web development has real difficulties, but these particular ones are softer there:
| Web application | Mobile application | |
|---|---|---|
| Recovering from bad state | A reload fixes most of it. The user presses refresh and the page rebuilds from the server. | There is no reload. Restarting means a cold launch, and whatever the user had typed is gone unless you saved it. |
| Shipping a fix | Deploy, and the next request serves the new code. | Submit, wait for review, then wait for users to update. Assume old versions stay in use. |
| Who controls the process | The browser tab lives while the user keeps it open. | The operating system suspends or terminates your app whenever it needs the memory. |
| Network assumptions | Usually present, usually fast, and a failure is visible immediately. | Sometimes absent, often slow, and sometimes neither connected nor failing. |
| Input | Pointer with hover, right-click, keyboard always available. | Touch with no hover, an on-screen keyboard that covers half the layout, and one hand holding the device. |
| Storage | Mostly server-side. Local storage is a convenience. | Local storage is often load-bearing, and the device can be lost or handed to someone else. |
Put those together and a pattern appears. On the web, the server is the application and the browser draws it. On a device, your app is a small application in its own right, with its own copy of data, its own idea of what is pending, and its own life independent of the server.
So the first design question for any screen is not how it looks. It is what the screen shows when the data is old, when the data is missing, and when the request is still in flight after eight seconds. Answer that up front and the layout follows. Leave it until later and you end up with a spinner that never resolves.
interface Employee {
id: number;
name: string;
department: string;
siteCode: string;
}
/** Every state the employee list can be in, named once. */
type ScreenState<T> =
| { status: "loading" }
| { status: "ready"; data: T; fetchedAt: number; stale: boolean }
| { status: "offline"; data: T | null; fetchedAt: number | null }
| { status: "failed"; message: string };
function statusLine(state: ScreenState<Employee[]>): string {
switch (state.status) {
case "loading":
return "Loading the site team";
case "ready":
return state.stale ? "Saved copy, refreshing now" : "Up to date";
case "offline":
return state.data
? "No connection. Showing the copy saved on this device."
: "No connection, and nothing saved for this site yet.";
case "failed":
return state.message;
}
}- The shape is the lesson here, not the syntax. Any language and any toolkit can express this; what matters is that the states are written down as a closed set instead of being implied by three loose boolean flags.
- Offline is its own state, separate from failure. "No connection, showing a saved copy" and "the server rejected that" ask completely different things of the user, so an app that shows one message for both is lying about one of them.
- The ready state carries fetchedAt and stale. Data on a device has an age, and the user is entitled to know it. A list from nine hours ago looks identical to a fresh one unless you say otherwise.
- Because the union is closed, the switch has to handle every case. Add a fifth state later and the compiler points at the code that has not caught up — which is far better than discovering the gap on a device in a basement.
Summary
- The operating system owns your process and can suspend or terminate your app at any time, so memory-only state is temporary by default
- Connectivity is intermittent and sometimes neither working nor failing, which makes timeouts and a real offline state part of the design rather than polish
- Touch, limited screen area and battery push you toward one task per screen, generous targets and fetching on demand instead of polling
- Store review and slow user updates mean a fix takes days and old clients keep calling your API for months
- A responsive website avoids most of this, so choose a device app for the capabilities it genuinely adds
Practice
Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.
Think about it
Three states for one screen
The field app has a screen listing today's site visits, fetched from the employees API.
Write down what the user sees in three situations: the app is opened in a plant room with no signal and has never fetched this list; the app is opened there having fetched it at 07:00; and the request has been running for twelve seconds on a weak connection.
For each one, say what the user can still do.
Show solution
No signal and nothing saved is the only genuinely empty case. Say plainly that there is no connection and no saved copy, and offer a retry. Avoid a bare empty list, because "no visits today" and "I could not find out" are different facts and the user will act on them differently.
No signal with a 07:00 copy is the interesting one. Show the list, label it with the time it was fetched, and let the engineer read it and add notes. The value of a local copy is precisely that the screen still works, and the age label is what stops it becoming a lie.
Twelve seconds in, you should already have given up. Around eight to ten seconds is a common ceiling for a foreground request; past that the user has concluded it is broken. Stop the request, show the saved copy if you have one, and offer retry.
The reason this exercise comes before any UI work: the answers decide what the screen contains. A design that has nowhere to put "saved at 07:00" was drawn without these three cases in mind, and it will be redrawn later.
Challenge
Write the constraint list for a real feature
The field app is to gain photo attachments on a visit note. An engineer photographs a piece of equipment, and the photo is stored against the visit record in the employees API.
Work through the six constraints from this lesson and write one concrete consequence of each for this feature. Then decide what happens to a photo taken with no signal.
Show solution
Connectivity: a photo is large enough that upload will frequently fail part-way through. It has to be recorded locally first and uploaded as a separate step, which means an upload queue and a visible state per photo.
Battery and data: uploading several megabytes over a weak mobile connection is one of the more expensive things the app can do. Many teams offer an on-wifi-only option, and telling the user what is pending is part of earning that trust.
Screen area: a full-size photo occupies the whole screen, so the visit note needs thumbnails with a way to open one, not a gallery embedded in a form.
Touch: the capture and delete controls need generous, well-separated targets. Deleting the wrong photo because two small icons sat next to each other is unrecoverable, since the original is often not in the camera roll.
Lifecycle: the app can be terminated while the upload is in flight. The queue has to survive on disk, and the upload has to be resumable or safely repeatable, which means the server needs to recognise a repeated attempt rather than storing the photo twice.
Store review: a feature using the camera needs a permission prompt with an honest explanation, and reviewers do check that the stated reason matches what the app does.
With no signal, the photo is saved on the device and queued. Tell the user it is waiting, not that it was sent. Quietly claiming success and losing the file later is the failure mode that destroys confidence in an app, because by the time anyone notices, the equipment has been repaired and the evidence is gone.
Knowledge check
Nothing is recorded and there is no score. The explanation appears either way.
Saved in this browser only.