Key Android Interview Topics: MVC/MVP/MVVM, Volley Cache, Concurrency, and More
This article compiles essential Android interview knowledge, covering MVC, MVP, and MVVM patterns, Volley disk cache mechanics and optimization, bitmap memory handling, heartbeat packet types, HashMap internals, and the differences among atomic, volatile, and synchronized constructs, while highlighting relevant design patterns.
MVC, MVP and MVVM
MVC communication (ring)
1. View sends command to Controller. 2. Controller performs business logic and asks Model to change state. 3. Model sends new data to View, providing feedback. All communication is unidirectional.
MVP communication
All parts communicate bidirectionally. View and Model never interact directly; they communicate through Presenter. View is a passive view with no business logic, while Presenter contains most logic.
MVVM as an upgrade of MVP
Same as MVP but adds two‑way data binding: changes in View automatically update ViewModel and vice versa.
Reference: http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html
In Android apps, the Model represents data structures and classes unrelated to the View, such as database access.
Why developers often read/write the database directly in an Activity? Because it is simple, but adding an interface and implementation class for data access may be unnecessary for small tasks.
In MVP, the Presenter should handle view‑related logic, while business logic belongs to a separate class or the Presenter itself. EventBus is typically used within the Presenter layer.
In MVVM, the Model changes the View only through the ViewModel; Model and View do not interact directly.
Definition of Architecture
Architecture is an abstract description of the overall software structure and components, guiding the design of large systems. It is essentially the skeleton of a software project.
Volley Cache
Disk cache implementation
Volley writes each network response to a local file using FileOutputStream. The cache directory can grow without limit, potentially exhausting storage.
Volley addresses this with DiskBasedCache#pruneIfNeeded().
private void pruneIfNeeded(int neededSpace) {
if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes) {
return;
}
long before = mTotalSize;
int prunedFiles = 0;
long startTime = SystemClock.elapsedRealtime();
Iterator<Map.Entry<String, CacheHeader>> iterator = mEntries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, CacheHeader> entry = iterator.next();
CacheHeader e = entry.getValue();
boolean deleted = getFileForKey(e.key).delete();
if (deleted) {
mTotalSize -= e.size;
} else {
// print log
}
iterator.remove();
prunedFiles++;
if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) {
break;
}
}
}mMaxCacheSizeInBytes defaults to 5 MB if not specified. The method receives neededSpace, checks if adding it would exceed the limit, and removes cached entries (first expired, then least‑recently‑used) until enough space is available. HYSTERESIS_FACTOR is 0.9.
Improving cache hit rate
Instead of deleting arbitrary entries, first remove expired items, then apply an LRU policy.
Cache filename generation
Volley splits the cache key into two halves, hashes each part, and concatenates the results to reduce filename collisions.
private String getFilenameForKey(String key) {
int firstHalfLength = key.length() / 2;
String localFilename = String.valueOf(key.substring(0, firstHalfLength).hashCode());
localFilename += String.valueOf(key.substring(firstHalfLength).hashCode());
return localFilename;
}String.hashCode() combines character values with a multiplier of 31; collisions are possible, so splitting the key lowers the probability of duplicate filenames.
Push heartbeat packets
Heartbeat packets are sent using socket.sendUrgentData(0xFF), which is a TCP urgent data packet.
ARGB_8888 memory usage
ARGB_8888 uses 4 bytes per pixel (8 bits for each channel). Bitmap decoding can be performed with inJustDecodeBounds=true to query dimensions without allocating pixel memory.
public static Bitmap create(byte[] bytes, int maxWidth, int maxHeight) {
// ... set options, decode bounds, calculate desired size, decode bitmap, scale if needed ...
return bitmap;
}Design patterns in Activity lifecycle
The lifecycle methods (onCreate, onStart, etc.) can be viewed as an implementation of the Template Method pattern, where the framework defines the algorithm skeleton and subclasses provide specific behavior. Some implementations also use the Proxy pattern via AppCompatDelegate.
HashMap internals
HashMap stores entries in an array indexed by the hash of the key. Collisions are resolved by probing subsequent slots.
Atomic, volatile, synchronized differences
volatileguarantees visibility of writes to other threads but does not provide atomicity; it is unsuitable for compound actions like i++. synchronized provides mutual exclusion for a block of code, ensuring atomicity. AtomicInteger offers lock‑free atomic operations, often more performant under high contention. ThreadLocal provides thread‑confined storage, useful for per‑thread data without static sharing.
Other considerations
When designing internal libraries, pay attention to JAR size and method count. Design patterns should be applied naturally rather than memorized.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
