Software projects rarely stay small. Features grow, requirements change, and teams expand. When data access logic is tightly coupled with business logic, even a simple update can break multiple parts of the system. This is where the Repository Pattern becomes extremely valuable. In this blog, we’ll explain the Repository Pattern in a clear and beginner-friendly...
If you’ve ever used Hilt in a Jetpack Compose app, you’ve probably written code like this: Kotlinclass MyRepository @Inject constructor( @ApplicationContext private val context: Context ) And then paused for a second and thought: “Okay… but where is this @ApplicationContext coming from?” “Who creates it?” “And how does Hilt magically inject it at runtime?” This article answers...
Navigating through code efficiently is crucial for productive Android development. Android Studio provides powerful back and forward navigation features that help you jump between different code locations, making it easier to trace code flow, review changes, and return to previous working contexts. In this comprehensive guide, we’ll explore everything you need to know about implementing...
Android background execution is one of the most misunderstood parts of the platform, especially when alarms, notifications, and device reboot come into play. Most tutorials show what code to write. Very few explain why that code works, what Android is doing internally, or why certain architectural rules are non-negotiable. This article fills that gap. We’ll...
If you’ve ever opened GitHub and noticed the wrong name on your commits — or spotted a commit on your main branch that never should’ve been there. These are some of the most common (and stressful) Git problems developers run into, especially when working in teams or switching between multiple accounts.
The good news is this: Git gives you the tools to fix both issues cleanly. The bad news? Using the wrong command can make things worse if you don’t understand what’s really going on.
This guide walks you through:
Why Android Studio shows the wrong Git user
How to correctly change the Git author (without breaking anything)
How to fix commits that are already pushed
When to remove commits entirely vs safely reverting them
Best practices to avoid these problems in the future
Everything here is based on how Git actually works under the hood — not IDE myths.
Why Android Studio Shows the Wrong Git User
Let’s clear up the most common misunderstanding first:
Android Studio does not control your Git commit author. Git does.
Android Studio is just a client. When you click “Commit,” it asks Git two questions:
What is the author name?
What is the author email?
Git answers based on its configuration files. That’s it.
So changing your GitHub account inside Android Studio affects authentication (push and pull permissions), but it does not change the commit author. That’s why this issue keeps coming back.
How Git Decides Who You Are
Git identifies authors using two values:
user.name
user.email
These can exist at two levels:
Global — applies to all repositories on your machine
Local (project-specific) — applies only to the current repository
Git always prefers local settings over global ones.
The Correct Way to Change Git User in Android Studio (Recommended)
If you work on multiple projects or use more than one GitHub account, this is the safest approach.
Step 1: Open the Terminal in Android Studio
Open your project, then click Terminal at the bottom.
If something goes wrong, git reflog can usually save you.
Best Practices to Prevent These Issues
Always verify Git user before starting a project
Prefer project-level Git config
Use separate SSH keys for different accounts
Protect main branches with PR rules
Never force-push without coordination
Keep commit emails matching your GitHub account
Conclusion
Android Studio often gets blamed for Git problems it doesn’t actually control. Once you understand that Git owns identity and history, everything becomes easier to reason about — and fix.
By setting the correct Git user, managing SSH keys properly, and choosing the right strategy for removing commits, you can keep your repositories clean without disrupting your team.
If you treat Git history with intention instead of panic, it becomes a powerful tool instead of a constant source of stress.
…you’re dealing with one of the most common (and confusing) Android Studio startup issues.
It usually appears after a crash, a forced shutdown, or reopening the IDE too quickly. The good news is that this error does not mean your installation is broken. It’s a safety mechanism that fails to recover properly in real-world conditions.
This guide explains what’s actually happening under the hood, why it shows up more often on Windows, how it behaves on macOS and Linux, and how to fix — and prevent — it permanently.
What This Error Really Means
Android Studio is built on the JetBrains IntelliJ Platform, which enforces a single-instance lock.
When Android Studio starts, it does three important things:
Creates a lock file in its system directory
Binds to a local socket (internal communication port)
Registers itself as the active IDE instance
When you close Android Studio normally, all of that is cleaned up.
But if the IDE:
crashes,
is force-killed,
is interrupted by sleep or shutdown,
or hangs during indexing or Gradle sync,
those locks don’t always get released.
When you try to reopen Android Studio, it checks for those locks, assumes another instance is still running, and blocks startup to protect your data.
That’s when you see errors like:
DirectoryLock$CannotActivateException
Process is still running and does not respond
Address already in use
Connection refused
This behavior is intentional — but the recovery is imperfect.
Is this a particular OS problem?
No. This error is cross-platform and occurs on Windows, macOS, and Linux.
That said, Windows developers see it far more often, and there are clear technical reasons for that.
Why Windows Is Affected the Most
1. Fast Startup (Hybrid Shutdown) — Windows Fast Startup doesn’t fully terminate background processes. If Android Studio was open during shutdown, its locks may survive the reboot.
2. Aggressive File Locking — Windows uses mandatory file locks. If the IDE freezes or crashes, those locks are more likely to be left behind.
3. Antivirus & Defender Interference — Real-time scanners can delay or block the IDE’s socket binding, triggering false “already running” states.
4. Zombie Java Processes — If studio64.exe or its Java runtime crashes, Windows may leave it running invisibly in the background.
Result: Windows users encounter this error far more frequently than macOS or Linux users.
macOS: Less Common, Still Possible
macOS handles process cleanup more gracefully, which reduces the frequency — but doesn’t eliminate it.
Common macOS triggers include:
Force-quitting Android Studio
System sleep or sudden power loss
Corrupted IDE cache after a crash
Multiple user sessions sharing the same home directory
Because macOS is Unix-based, socket cleanup is usually reliable, but stale lock files can still remain after abnormal exits.
Linux: Rare, But Not Impossible
Linux is the least affected platform.
When the error appears, it’s usually caused by:
Killing the IDE with kill -9
Running Android Studio under different users
Permission issues in .config or .cache
Snap or Flatpak sandbox limitations
Linux aggressively cleans up sockets and file locks, which is why this issue is relatively rare there.
Real-World OS Comparison
Operating System
Likelihood
Overall Stability
Windows
High
Most problematic
macOS
Medium
Mostly stable
Linux
Low
Most reliable
Step-by-Step Fix (Works on Any OS)
1. Kill the Stuck Process (Most Common Fix)
Windows
Open Task Manager → Details
End studio64.exe or java.exe
macOS
Open Activity Monitor
Force quit Android Studio or Java
Linux
Bash
pkill-fandroid-studio
If the error shows a PID, target that process directly.
2. Delete Leftover Lock Files
Sometimes the process is gone, but the lock file remains.
If you’ve tried uploading an image directly or embedding one like you would on GitHub README files, you’ve probably noticed it’s not straightforward.
In this guide, we’ll walk through adding Images to GitHub Gists in detail. You’ll learn what works, what doesn’t, and why GitHub behaves the way it does. We’ll also cover reliable methods with clear examples you can use right away.
Why Adding Images to GitHub Gists Is Confusing
GitHub Gists look similar to repositories, but they’re not the same thing.
A few key differences matter here:
Gists are designed for small, single-purpose snippets
They don’t have a full file browser like repos
They don’t support direct image uploads through the UI
Because of this, adding Images to GitHub Gists require a different approach.
Can We Upload Images Directly to a GitHub Gist?
Short answer: No.
GitHub Gists do not support direct image uploads the way repositories do.
You can:
Paste text files
Add Markdown
Add code files
But you cannot:
Upload PNG, JPG, or GIF files directly
Drag and drop images into a Gist
That’s not a bug. It’s a design choice.
The Correct Way to Add Images to GitHub Gists
Even though you can’t upload images directly, you can display images in a Gist using external image hosting.
The idea is simple:
Host the image somewhere else
Embed it using Markdown
Let’s go through the working methods.
Method 1: Using GitHub Repository Images (Most Reliable)
This is the best and most stable way to add Images to GitHub Gists.
Step 1: Upload the Image to a GitHub Repository
Create a repository or use an existing one, then upload your image:
Markdown
my-repo/└── images/ └── img1.png
Once uploaded, click the image and copy the raw URL.
This method works, but reliability depends on the host.
What Does NOT Work (Common Mistakes)
Understanding what doesn’t work is just as important.
1. Relative Paths
This will not work in Gists:
Markdown

Why? Because Gists don’t have a file system like repositories.
2. HTML <img> Tags with Local Files
This also fails:
Markdown
<img src="image.png" />
The browser has no idea where image.png lives.
3. Dragging Images into Gists
You can drag images into GitHub issues, but not into Gists.
If you try, nothing happens.
Why GitHub Designed Gists This Way
GitHub Gists are meant to be:
Lightweight
Fast
Focused on code
Allowing image uploads would:
Increase storage costs
Complicate versioning
Move Gists away from their core purpose
That’s why adding Images to GitHub Gists rely on external hosting.
Best Practices for Adding Images to GitHub Gists
To keep your Gists clean and professional, follow these tips:
Use Descriptive Alt Text
Instead of:
Markdown

Use:
Markdown

This improves:
Accessibility
Search visibility
AI answer extraction
Keep Images Small and Relevant
Large images slow down loading and distract from the code.
Ask yourself:
Does this image explain something better than text?
Is it necessary?
If yes, include it. If not, skip it.
Version Your Images
If your image changes over time:
Store it in a repo
Update filenames or folders
This avoids broken references in old Gists.
Conclusion
Adding Images to GitHub Gists isn’t hard once you understand the rules.
You can’t upload images directly, but you can embed them reliably using external URLs. GitHub repositories are the safest option, while issue uploads and external hosts work in specific cases.
Use images sparingly, explain them clearly, and your Gists will be far more useful than plain code alone.
If you’ve built Android apps with Jetpack Compose, you’ve probably run into the question: Should I use ViewModel or rememberSaveable? Both help you keep state alive, but they work very differently depending on what’s happening to your app — like when the screen rotates or when the system kills your process. This post will break down ViewModel...
If you’ve ever worked with collections in Kotlin or Java, you’ve probably heard about Kotlin Sequences and Java Streams. Both are powerful tools for handling large amounts of data in a clean, functional style. But when should you use one over the other? And what’s the real difference between them?
This guide breaks it all down in simple way — no jargon overload. By the end, you’ll know exactly when to reach for Kotlin Sequences or Java Streams in your projects.
Why Do We Even Need Sequences or Streams?
Collections like List and Set are everywhere. But looping through them with for or while can quickly become messy, especially when you want to:
Filter elements
Map values
Reduce results into a single outcome
This is where lazy evaluation comes in. Instead of processing all elements up front, sequences and streams let you chain operations in a pipeline. The work only happens when you actually need the result. That means cleaner code and often better performance.
Kotlin Sequences: Lazy by Design
Kotlin’s Sequence is basically a wrapper around collections that delays execution until the final result is requested.
Filtering and Mapping with Sequences
Kotlin
funmain() {val numbers = listOf(1, 2, 3, 4, 5)val result = numbers.asSequence() .filter { it % 2 == 1 } // Keep odd numbers .map { it * it } // Square them .toList() // Trigger evaluationprintln(result) // [1, 9, 25]}
Here,
.asSequence() converts the list into a sequence.
filter and map are chained, but nothing actually runs yet.
.toList() triggers evaluation, so all steps run in a pipeline.
Key takeaway: Sequences process elements one by one, not stage by stage. That makes them memory-efficient for large datasets.
Java Streams: Functional Power in Java
Java introduced Stream in Java 8, giving developers a way to work with collections functionally.
Filtering and Mapping with Streams
Java
import java.util.*;import java.util.stream.*;publicclassStreamExample {publicstaticvoidmain(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> result = numbers.stream() .filter(n -> n % 2 == 1) // Keep odd numbers .map(n -> n * n) // Square them .toList(); // Collect into a listSystem.out.println(result); // [1, 9, 25] }}
How It Works
.stream() converts the collection into a stream.
Operations like filter and map are chained.
.toList() (or .collect(Collectors.toList()) in older Java versions) triggers evaluation.
Streams are also lazy, just like Kotlin Sequences. But they come with a big advantage: parallel processing.
Kotlin Sequences vs Java Streams: Key Differences
Here’s a side-by-side comparison of Kotlin Sequences or Java Streams:
When to Use Kotlin Sequences
You’re writing Kotlin-first code.
You want simple lazy evaluation.
You’re processing large collections where memory efficiency matters.
You don’t need parallel execution.
Example: processing thousands of lines from a text file efficiently.
When to Use Java Streams
You’re in a Java-based project (or interoperating with Java).
You want parallel execution to speed up heavy operations.
You’re working with Java libraries that already return streams.
Example: data crunching across millions of records using parallelStream().
Which Should You Choose?
If you’re in Kotlin, stick with Kotlin Sequences. They integrate beautifully with the language and make your code feel natural.
If you’re in Java or need parallel execution, Java Streams are the way to go.
And remember: it’s not about one being “better” than the other — it’s about choosing the right tool for your context.
Conclusion
When it comes to Kotlin Sequences or Java Streams, the choice boils down to your project’s ecosystem and performance needs. Both give you lazy, functional pipelines that make code cleaner and more maintainable.
Kotlin developers → Sequences
Java developers or parallel workloads → Streams
Now you know when to use each one, and you’ve seen them in action with real examples. So the next time you need to process collections, you won’t just write a loop — you’ll reach for the right tool and make your code shine.
Artificial Neural Networks (ANNs) are one of the driving forces behind today’s AI revolution. From recognizing faces in photos to powering voice assistants, they’re everywhere. But what exactly are they? And how do they mimic the human brain? Let’s break it down step by step.
What Are Artificial Neural Networks?
Artificial Neural Networks are computational models inspired by how the human brain processes information. Just like our brains use billions of interconnected neurons to learn and make decisions, ANNs use layers of artificial “neurons” to detect patterns, classify data, and make predictions.
At their core, ANNs are about finding relationships in data. Whether it’s images, text, or numbers, they can spot patterns we might miss.
How the Human Brain Inspires ANNs
The inspiration for ANNs comes directly from biology:
Neurons in the brain receive signals, process them, and pass them along if the signal is strong enough.
Artificial neurons work in a similar way: they take input, apply weights (importance), add them up, and pass the result through an activation function.
Think of it like this:
Neurons = nodes in a network.
Synapses = weights between nodes.
Brain learning = adjusting synapse strengths.
ANN learning = adjusting weights during training.
Anatomy of an Artificial Neural Network
Every ANN is built from layers:
Input Layer — Where data enters the network. Example: pixels of an image.
Hidden Layers — Where the “thinking” happens. These layers detect patterns, like edges, shapes, or textures.
Output Layer — Where results are produced. Example: labeling an image as a “cat” or “dog.”
Each connection between neurons has a weight, and learning means updating those weights to improve accuracy.
How ANNs Learn: The Training Process
Training an ANN is like teaching a child. You show it examples, it makes guesses, and you correct it until it improves. Here’s the typical process:
Forward Propagation — Data flows through the network, producing an output.
Loss Calculation — The network checks how far its prediction is from the correct answer.
Backward Propagation (Backprop) — The error flows backward through the network, adjusting weights to reduce mistakes.
Repeat — This cycle happens thousands or even millions of times until the network becomes accurate.
A Simple Neural Network in Python
Let’s build a tiny ANN to classify numbers using TensorFlow and Keras. Don’t worry — it’s simpler than it looks.
Python
import tensorflow as tffrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense# Step 1: Build the modelmodel = Sequential([ Dense(16, input_shape=(10,), activation='relu'), # hidden layer with 16 neurons Dense(8, activation='relu'), # another hidden layer Dense(1, activation='sigmoid') # output layer (binary classification)])# Step 2: Compile the modelmodel.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])# Step 3: Train the model with dummy dataimport numpy as npX = np.random.rand(100, 10) # 100 samples, 10 features eachy = np.random.randint(2, size=100) # 100 labels (0 or 1)model.fit(X, y, epochs=10, batch_size=8)
Dense layers: These are fully connected layers where every neuron talks to every neuron in the next layer.
Activation functions: relu helps capture complex patterns; sigmoid squashes outputs between 0 and 1, making it great for yes/no predictions.
Optimizer (adam): Decides how the network updates its weights.
Loss function (binary_crossentropy): Measures how far off predictions are from actual results.
Training (fit): This is where learning happens—weights get adjusted to reduce errors.
Why Artificial Neural Networks Matter
Artificial Neural Networks power much of modern AI, including:
Natural language processing (chatbots, translation apps)
Healthcare (disease prediction, drug discovery)
Finance (fraud detection, stock predictions)
Their strength lies in adaptability: once trained, they can generalize knowledge and apply it to new, unseen data.
Challenges of ANNs
While powerful, ANNs have challenges:
Data hungry: They need lots of examples to learn.
Black box problem: It’s often hard to understand why a network makes certain decisions.
Computational cost: Training large ANNs requires heavy computing power.
Researchers are working on making them more efficient and interpretable.
Conclusion
Artificial Neural Networks are one of the best examples of how humans have borrowed ideas from nature — specifically the brain — to solve complex problems. They’re not truly “intelligent” in the human sense, but their ability to learn from data is transforming industries.
As we move forward, ANNs will continue to evolve, becoming more powerful and more transparent. Understanding the basics today means you’ll be ready for the AI-powered world of tomorrow.