Add readme.md
This commit is contained in:
546
readme.md
Normal file
546
readme.md
Normal file
@@ -0,0 +1,546 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 📚 درسنامه جامع خودآموز برنامهنویسی موبایل
|
||||||
|
|
||||||
|
## Kotlin + Android + Jetpack Compose
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش اول: روشهای توسعه اپلیکیشن موبایل
|
||||||
|
|
||||||
|
در دنیای مهندسی نرمافزار، برای اینکه یک ایده را تبدیل به یک اپلیکیشن موبایل کنیم و آن را در اختیار کاربران قرار دهیم، سه استراتژی و روش اصلی وجود دارد. انتخاب هر کدام از این روشها مستقیماً روی هزینه، زمان و کیفیت نهایی پروژه تأثیر میگذارد.
|
||||||
|
|
||||||
|
## ۱. توسعه بومی (Native Development)
|
||||||
|
|
||||||
|
توسعه نیتیو یا بومی به این معناست که ما اپلیکیشن را دقیقاً با استفاده از زبانهای رسمی و ابزارهای استاندارد معرفیشده توسط شرکت سازنده آن سیستمعامل (گوگل برای اندروید و اپل برای آیاواس) میسازیم. در این روش، شما برای هر سیستمعامل یک پروژه کاملاً مجزا باز میکنید.
|
||||||
|
|
||||||
|
* **Android:** توسعه با زبان **Kotlin** یا Java در محیط Android Studio
|
||||||
|
* **iOS:** توسعه با زبان **Swift** یا Objective-C در محیط Xcode
|
||||||
|
|
||||||
|
### مزایا
|
||||||
|
|
||||||
|
* **بهترین عملکرد (Performance):** به دلیل کدنویسی مستقیم و بدون واسطه، برنامه با حداکثر سرعت سختافزار اجرا میشود.
|
||||||
|
* **مصرف بهینه باتری:** ابزارهای نیتیو کمترین فشار را به پردازنده و باتری دستگاه وارد میکنند.
|
||||||
|
* **دسترسی بیواسطه به سختافزار:** به محض معرفی یک قابلیت جدید در گوشیها (مثل سنسور اثر انگشت جدید یا دوربینهای چندگانه)، در نسخه نیتیو فوراً به آن دسترسی دارید.
|
||||||
|
* **تجربه کاربری (UX) استاندارد:** رفتارهای انیمیشنها و اجزای صفحه کاملاً با ساختار سیستمعامل همخوانی دارد.
|
||||||
|
|
||||||
|
### معایب
|
||||||
|
|
||||||
|
* **هزینه توسعه بسیار بالا:** شما مجبورید دو تیم مجزا (یک تیم اندروید و یک تیم iOS) استخدام کنید.
|
||||||
|
* **زمان توسعه بیشتر:** هر قابلیت جدید باید یکبار برای اندروید و یکبار برای iOS به طور جداگانه کدنویسی و تست شود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ۲. توسعه چندپلتفرمی (Cross-Platform)
|
||||||
|
|
||||||
|
فلسفه این روش **"یکبار بنویس، همهجا اجرا کن" (Write Once, Run Anywhere)** است. در این استراتژی، شما با استفاده از یک زبان برنامهنویسی و یک فریمورک، کدی مینویسید که خروجی آن هم روی اندروید و هم روی iOS کار میکند.
|
||||||
|
|
||||||
|
فریمورکهای مطرح بازار:
|
||||||
|
|
||||||
|
* **Flutter:** توسعهیافته توسط گوگل (با زبان Dart)
|
||||||
|
* **React Native:** توسعهیافته توسط متا/فیسبوک (با زبان JavaScript/TypeScript)
|
||||||
|
* **Kotlin Multiplatform (KMP):** ابزار مدرن JetBrains که اجازه میدهد منطق برنامه (Logic) بین پلتفرمها مشترک باشد.
|
||||||
|
|
||||||
|
### مزایا
|
||||||
|
|
||||||
|
* **کاهش چشمگیر زمان توسعه:** به جای توسعه دو برنامه، عملاً یک برنامه توسعه داده میشود.
|
||||||
|
* **یک تیم توسعه:** مدیریت یک تیم که به یک زبان مسلط هستند بسیار سادهتر است.
|
||||||
|
* **کاهش هزینهها:** برای استارتاپها یا شرکتهایی با بودجه محدود بسیار اقتصادی است.
|
||||||
|
|
||||||
|
### معایب
|
||||||
|
|
||||||
|
* **عملکرد کمتر نسبت به Native:** وجود یک لایه واسط برای تبدیل کدها به زبان سختافزار، کمی از سرعت برنامه میکاهد (گرچه در برنامههای عادی حس نمیشود).
|
||||||
|
* **وابستگی به بهروزرسانی فریمورک:** اگر گوگل یا اپل ویژگی سختافزاری جدیدی معرفی کنند، باید منتظر بمانید تا توسعهدهندگان فریمورک کراسپلتفرم، آن را پشتیبانی کنند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ۳. توسعه وب یا ترکیبی (Hybrid / Web-based)
|
||||||
|
|
||||||
|
در این روش، اپلیکیشن شما در واقع یک سایت است که با ابزارهای فرانتاند وب (HTML, CSS, JavaScript) ساخته شده و درون یک مرورگر داخلیِ بدون لبه به نام **WebView** در داخل موبایل نمایش داده میشود. کاربر تصور میکند یک اپلیکیشن نصب کرده، اما در واقع دارد یک سایت را تماشا میکند.
|
||||||
|
|
||||||
|
ابزارهای معروف:
|
||||||
|
|
||||||
|
* **Ionic**
|
||||||
|
* **Cordova**
|
||||||
|
* **Capacitor**
|
||||||
|
|
||||||
|
### مزایا
|
||||||
|
|
||||||
|
* **سریعترین روش ساخت:** برای شرکتهایی که سایت دارند و میخواهند سریعاً یک نسخه موبایل در بازار داشته باشند عالی است.
|
||||||
|
* **استفاده از تخصص وب:** نیازی به یادگیری ابزارهای موبایل نیست؛ تیم وب شرکت میتواند آن را هندل کند.
|
||||||
|
|
||||||
|
### معایب
|
||||||
|
|
||||||
|
* **عملکرد ضعیف و کندی ملموس:** انیمیشنها و اسکرولها ممکن است لگ داشته باشند.
|
||||||
|
* **تجربه کاربری ضعیف:** حس و حال یک اپلیکیشن واقعی موبایل را به کاربر منتقل نمیکند.
|
||||||
|
* **دسترسی بسیار محدود:** دسترسی به بخشهای عمیق سختافزار و سیستمعامل در این روش بسیار دشوار یا غیرممکن است.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش دوم: معرفی زبان Kotlin
|
||||||
|
|
||||||
|
در سال ۲۰۱۷، گوگل رسماً **Kotlin** را به عنوان زبان اول و ترجیحی (First-class) برای توسعه اندروید معرفی کرد و جایگزین جاوا شد. کاتلین توسط شرکت **JetBrains** (سازنده بزرگترین ابزارهای برنامهنویسی) طراحی شده است تا مشکلات و سختیهای زبان جاوا را حل کند.
|
||||||
|
|
||||||
|
### چرا کاتلین؟
|
||||||
|
|
||||||
|
* **خوانایی بالا و سادگی:** کدهای کاتلین بسیار تمیز و شبیه به زبان انگلیسی هستند. خبری از کدهای طولانی و تکراری (Boilerplate) جاوا نیست.
|
||||||
|
* **ایمنی در برابر خطای نال (Null Safety):** کاتلین به گونهای طراحی شده که جلوی خطای معروف "NullPointerException" (که علت کرش کردن نصف برنامههای اندرویدی قدیمی بود) را در همان زمان نوشتن کد میگیرد.
|
||||||
|
* **مدرن و پیشرفته:** از تمام قابلیتهای برنامهنویسی شیءگرا (OOP) و برنامهنویسی تابعی (Functional) پشتیبانی میکند.
|
||||||
|
* **سازگاری ۱۰۰ درصدی با جاوا (Interoperability):** شما میتوانید در یک پروژه اندرویدی، نیمی از کدها را به زبان جاوا و نیمی دیگر را به زبان کاتلین بنویسید و آنها بدون هیچ مشکلی در کنار هم کار خواهند کرد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش سوم: متغیرها در Kotlin
|
||||||
|
|
||||||
|
متغیرها مانند ظرفهایی در حافظه رم (RAM) دستگاه هستند که دادههای ما را نگهداری میکنند. در کاتلین، نوع تعریف این ظرف مشخص میکند که آیا محتوای داخل آن در آینده قابل تغییر است یا خیر. این تفکیک به امنیت و پایداری برنامه کمک زیادی میکند.
|
||||||
|
|
||||||
|
## val (مخفف Value)
|
||||||
|
|
||||||
|
این کلمه کلیدی برای تعریف **متغیرهای ثابت یا غیرقابل تغییر (Immutable)** استفاده میشود. وقتی یکبار به آن مقدار دادید، دیگر در طول اجرای برنامه نمیتوانید مقدارش را عوض کنید. (شبیه به ثابتها در ریاضی).
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val age = 20
|
||||||
|
// age = 21 -> این خط باعث خطای کمپایل میشود و برنامه اجرا نخواهد شد!
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
> **نکته حرفهای:** همیشه در کاتلین فرض را بر استفاده از `val` بگذارید، مگر اینکه مطمئن باشید مقدار آن متغیر در آینده قطعاً تغییر خواهد کرد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## var (مخفف Variable)
|
||||||
|
|
||||||
|
این کلمه کلیدی برای تعریف **متغیرهای قابل تغییر (Mutable)** استفاده میشود. ظرفی است که هر زمان خواستید، میتوانید محتوای قدیمی آن را پاک کنید و مقدار جدیدی درونش قرار دهید.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
var score = 10
|
||||||
|
score = 20 // مقدار امتیاز با موفقیت به ۲۰ تغییر یافت
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش چهارم: انواع داده (Data Types)
|
||||||
|
|
||||||
|
کاتلین یک زبان **Statically Typed** است؛ یعنی نوع دادهی هر متغیر باید مشخص باشد. البته کاتلین هوشمند است (Type Inference) و خودش از روی مقداری که به متغیر میدهید، نوع آن را حدس میزند، اما ما میتوانیم خودمان هم نوع آن را صراحتاً بعد از دونقطه (`:`) مشخص کنیم.
|
||||||
|
|
||||||
|
### Int (Integer)
|
||||||
|
|
||||||
|
برای ذخیرهسازی اعداد صحیح (بدون اعشار) مثبت و منفی استفاده میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val age: Int = 25
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Double
|
||||||
|
|
||||||
|
برای ذخیرهسازی اعداد اعشاری با دقت بالا استفاده میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val price: Double = 19.5
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### String
|
||||||
|
|
||||||
|
برای ذخیرهسازی متنها و رشتههای متنی استفاده میشود. مقادیر String باید داخل دابلکوتیشن (`""`) قرار بگیرند.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val name: String = "Ali"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Boolean
|
||||||
|
|
||||||
|
برای متغیرهای منطقی که فقط دو حالت دارند استفاده میشود: درست (`true`) یا غلط (`false`). از این نوع داده در شرطها استفاده زیادی میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val isOnline: Boolean = true
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش پنجم: شرطها (Conditions)
|
||||||
|
|
||||||
|
برنامهها برای اینکه هوشمند به نظر برسند، نیاز دارند تا در شرایط مختلف تصمیمگیری کنند. در کاتلین دو ابزار اصلی برای بررسی شرطها داریم.
|
||||||
|
|
||||||
|
## دستور if و else
|
||||||
|
|
||||||
|
زمانی استفاده میشود که میخواهیم یک یا چند شرط ساده را بررسی کنیم. اگر شرط داخل پرانتز درست باشد، کدهای داخل بلاکِ `if` اجرا میشوند؛ در غیر این صورت کدهای بلاک `else`.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val age = 18
|
||||||
|
|
||||||
|
if (age >= 18) {
|
||||||
|
println("بزرگسال") // اگر سن مساوی یا بیشتر از ۱۸ باشد
|
||||||
|
} else {
|
||||||
|
println("نابالغ") // اگر سن کمتر از ۱۸ باشد
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## دستور when (نسخه پیشرفته و قدرتمند switch)
|
||||||
|
|
||||||
|
وقتی تعداد حالتهای یک متغیر زیاد باشد، استفاده از `if-else`های متوالی کد را کثیف میکند. دستور `when` متغیر را میگیرد و آن را با حالتهای مختلف مقایسه میکند. خوانایی این دستور فوقالعاده بالا است.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val day = 3
|
||||||
|
|
||||||
|
when(day) {
|
||||||
|
1 -> println("شنبه")
|
||||||
|
2 -> println("یکشنبه")
|
||||||
|
3 -> println("دوشنبه")
|
||||||
|
else -> println("نامشخص") // مانند default در زبانهای دیگر عمل میکند
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش ششم: حلقهها (Loops)
|
||||||
|
|
||||||
|
حلقهها برای تکرار اجرای یک سری از کدها به تعداد مشخص یا تا زمان برقرار بودن یک شرط استفاده میشوند تا از نوشتن کدهای تکراری جلوگیری کنند.
|
||||||
|
|
||||||
|
## حلقه while
|
||||||
|
|
||||||
|
این حلقه ابتدا شرط را بررسی میکند؛ اگر شرط درست (`true`) باشد، کدهای داخلش را اجرا میکند و این کار را آنقدر تکرار میکند تا زمانی که شرط بالاخره غلط (`false`) شود. **مواظب حلقههای تکرار بینهایت باشید!**
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
while(i < 5) {
|
||||||
|
println(i)
|
||||||
|
i++ // در هر بار تکرار، یک واحد به متغیر اضافه میشود تا بالاخره شرط ۵ شدن برقرار شود
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## حلقه for
|
||||||
|
|
||||||
|
این حلقه برای پیمایش (حرکت روی) یک بازه عددی یا اعضای یک لیست استفاده میشود. در کاتلین تعریف این حلقه بسیار ساده و روان است.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// این حلقه اعداد ۱ تا ۵ (خود ۵ هم شامل میشود) را به ترتیب چاپ میکند
|
||||||
|
for(i in 1..5){
|
||||||
|
println(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش هفتم: توابع (Functions)
|
||||||
|
|
||||||
|
توابع قطعه کدهایی هستند که یک کار مشخص را انجام میدهند. ما کدهایمان را دستهبندی کرده و درون یک تابع میگذاریم تا بتوانیم بارها و بارها از آن در جاهای مختلف برنامه بدون نیاز به دوبارهنویسی استفاده کنیم. توابع در کاتلین با کلمه کلیدی `fun` تعریف میشوند.
|
||||||
|
|
||||||
|
### ۱. تابع ساده (بدون ورودی و خروجی)
|
||||||
|
|
||||||
|
فقط یک کار را انجام میدهد و تمام میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun sayHello() {
|
||||||
|
println("Hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### ۲. تابع دارای پارامتر (ورودی)
|
||||||
|
|
||||||
|
اطلاعاتی را از بیرون دریافت میکند تا بر اساس آن کارش را انجام دهد.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun greet(name: String) {
|
||||||
|
println("Hello $name") // استفاده از تکنینک String Interpolation با علامت $
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### ۳. تابع دارای مقدار بازگشتی (خروجی)
|
||||||
|
|
||||||
|
پس از انجام محاسبات، نتیجه را به جایی که تابع فراخوانی شده پس میدهد. نوع داده خروجی بعد از پرانتزها با `:` مشخص میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun sum(a: Int, b: Int): Int {
|
||||||
|
return a + b // با کلمه کلیدی return مقدار را پس میفرستد
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش هشتم: لیستها (Collections)
|
||||||
|
|
||||||
|
برای ذخیره مجموعهای از دادههای همنوع در یک متغیر واحد، از لیستها استفاده میکنیم. در کاتلین دو نوع لیست اصلی وجود دارد تا امنیت دادهها حفظ شود.
|
||||||
|
|
||||||
|
## List (فقط خواندنی - Immutable)
|
||||||
|
|
||||||
|
لیستی است که پس از ساخته شدن، اندازه و آیتمهای درون آن **قابل تغییر، حذف یا اضافه کردن نیستند**. شما فقط میتوانید اطلاعات آن را بخوانید.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val numbers = listOf(1, 2, 3, 4)
|
||||||
|
// numbers.add(5) -> خطای کمپایل! این لیست متد ساختاری برای اضافه کردن ندارد.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MutableList (قابل تغییر)
|
||||||
|
|
||||||
|
اگر نیاز دارید در طول برنامه به لیست خود عضو جدیدی اضافه کنید، عضوی را حذف کنید یا مقدار آن را ویرایش کنید، باید از این نوع لیست استفاده کنید.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val numbers = mutableListOf(1, 2, 3)
|
||||||
|
|
||||||
|
numbers.add(4) // عدد ۴ با موفقیت به انتهای لیست اضافه شد
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش نهم: Null Safety (امنیت در برابر مقدار تهی)
|
||||||
|
|
||||||
|
در بسیاری از زبانها مثل جاوا، اگر بخواهید به متغیری دسترسی پیدا کنید که هیچ مقداری ندارد (یعنی `null` است)، برنامهتان فوراً کرش میکند. کاتلین با سیستم Null Safety این مشکل را حل کرده است. در حالت عادی، هیچ متغیری در کاتلین حق ندارد مقدار `null` بگیرد.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// var name: String = null -> خطای کمپایل! کاتلین اجازه نمیدهد.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
اگر سیستمی دارید که واقعاً نیاز دارد مقدار نال بپذیرد (مثلا نام کاربری که هنوز ثبت نام نکرده)، باید از علامت سوال `?` جلوی نوع داده استفاده کنید:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
var name: String? = null // این متغیر Nullable است، یعنی مجاز به داشتن نال است
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### استفاده امن با Safe Call Operator (`?.`)
|
||||||
|
|
||||||
|
حالا اگر بخواهید طول این متن را بگیرید، چون متغیر ممکن است نال باشد، کاتلین اجازه دسترسی مستقیم نمیدهد. باید از `?.` استفاده کنید. این یعنی: "اگر متغیر نال نبود طولش را بده، و اگر نال بود، کل خروجی را نال برگردان و کرش نکن."
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
println(name?.length) // بدون کرش کردن، مقدار null را چاپ میکند
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش دهم: معرفی Android Studio
|
||||||
|
|
||||||
|
محیط اندروید استودیو (Android Studio) نرمافزار رسمی گوگل برای طراحی و برنامهنویسی اپلیکیشنهای اندروید است. این محیط مجهز به ابزارهای بسیار پیشرفتهای است که فرآیند کدنویسی را ساده میکنند. برای اینکه اندروید استودیو کار کند، به سه بخش کلیدی زیر تکیه دارد:
|
||||||
|
|
||||||
|
### JDK (Java Development Kit)
|
||||||
|
|
||||||
|
کیت توسعه جاوا؛ کاتلین برای اجرا شدن روی سیستمعامل نیاز دارد کدهایش به کدهای قابل فهم برای ماشین (Bytecode) تبدیل شوند. JDK ابزارها و موتور اصلی این فرآیند را فراهم میکند.
|
||||||
|
|
||||||
|
### SDK (Software Development Kit)
|
||||||
|
|
||||||
|
کیت توسعه نرمافزار اندروید؛ مجموعهای از تمام ابزارها، کدهای پیشفرض، شبیهسازها و کتابخانههایی است که گوگل ساخته تا برنامهنویس بتواند با سیستمعامل اندروید، دوربین، جیپیاس و... ارتباط برقرار کند. هر نسخه اندروید (مثلا اندروید ۱۳ یا ۱۴) یک SDK اختصاصی دارد.
|
||||||
|
|
||||||
|
### Gradle (سیستم Build پروژه)
|
||||||
|
|
||||||
|
گریدل مغز متفکر مدیریت پروژه شماست. گریدل یک ابزار خودکارسازی است که وظایف زیر را بر عهده دارد:
|
||||||
|
|
||||||
|
* دانلود تمام کتابخانههای خارجی که در پروژه نیاز دارید.
|
||||||
|
* کامپایل کردن تمام کدهای کاتلین و منابع.
|
||||||
|
* بستهبندی نهایی پروژه و تحویل فایل خروجی قابل نصب روی گوشی (**APK** یا **AAB**).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش یازدهم: ساختار پروژه اندروید
|
||||||
|
|
||||||
|
وقتی یک پروژه جدید در اندروید استودیو میسازید، فایلهای زیادی تولید میشوند. ساختار زیر مهمترین بخشهایی است که یک برنامهنویس روزانه با آنها سر و کار دارد:
|
||||||
|
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
├── manifests
|
||||||
|
│ └── AndroidManifest.xml
|
||||||
|
├── java/
|
||||||
|
│ └── MainActivity.kt
|
||||||
|
├── res/
|
||||||
|
│ ├── drawable
|
||||||
|
│ ├── values
|
||||||
|
│ └── layout
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### AndroidManifest.xml (شناسنامه اپلیکیشن)
|
||||||
|
|
||||||
|
مهمترین فایل پروژه است که نقش شناسنامه برنامه را دارد. سیستمعامل اندروید قبل از اجرای برنامه این فایل را میخواند. مواردی مثل نام اپلیکیشن، آیکون، دسترسیها (پرمیژنها مثل دسترسی به اینترنت یا دوربین) و لیست تمام صفحاتی که در برنامه وجود دارند، در اینجا ثبت میشود.
|
||||||
|
|
||||||
|
### پوشه java (یا kotlin)
|
||||||
|
|
||||||
|
محل قرارگیری تمام کدهای منطقی برنامه شما به زبان کاتلین است. نام جاوا به دلایل تاریخی و سنتی روی این پوشه باقی مانده است. کدهایی مثل `MainActivity.kt` در این پوشه جا دارند.
|
||||||
|
|
||||||
|
### پوشه res (مخفف Resources)
|
||||||
|
|
||||||
|
تمام منابع بصری و غیرکدنویسی برنامه در این پوشه قرار میگیرند:
|
||||||
|
|
||||||
|
* **drawable:** تصاویر، آیکونها و شکلهای گرافیکی.
|
||||||
|
* **values:** فایلهای متنی شامل رنگها (`colors.xml`) و متنهای ثابت برنامه (`strings.xml` جهت چندزبانه کردن اپلیکیشن).
|
||||||
|
* **layout:** در سیستمهای قدیمی اندروید، فایلهای طراحی ظاهر صفحات (XML) در اینجا قرار میگرفتند (در Jetpack Compose کاربرد این بخش بسیار کمتر شده است).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش دوازدهم: Activity چیست؟
|
||||||
|
|
||||||
|
یک **Activity** نقطه ورود اصلی برنامه و معادل **یک صفحه کامل از اپلیکیشن** است که کاربر میتواند آن را ببیند و با آن تعامل داشته باشد. هر زمان که شما در برنامه جابجا میشوید (مثلاً از صفحه لیست محصولات به صفحه جزئیات محصول میروید)، در واقع دارید از یک Activity به Activity دیگری منتقل میشوید.
|
||||||
|
|
||||||
|
نمونه کد یک اکتیویتی ساده و مدرن:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// اکتیویتی ما از ComponentActivity ارثبری میکند تا قابلیتهای صفحه را داشته باشد
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
// این متد مانند نقطه شروع و متد main صفحه است که به محض باز شدن صفحه اجرا میشود
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// متد setContent مشخص میکند چه چیزی باید روی صفحه نمایش داده شود (مخصوص Jetpack Compose)
|
||||||
|
setContent {
|
||||||
|
Text("Hello Android") // نمایش یک متن ساده روی صفحه گوشی
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش سیزدهم: Jetpack Compose
|
||||||
|
|
||||||
|
در گذشته، ساخت ظاهر برنامه (UI) در اندروید با استفاده از زبان XML انجام میشد که کاری طاقتفرسا بود و ارتباط دادن آن به کدهای کاتلین پیچیدگی زیادی داشت. گوگل با معرفی **Jetpack Compose** این سیستم را کاملاً دگرگون کرد.
|
||||||
|
|
||||||
|
Jetpack Compose یک فریمورک مدرن، مدرن و کاملاً کدنویسیشده با **کاتلین** برای طراحی رابط کاربری (UI) است. دیگر نیازی به هیچ فایل XML نیست؛ هم ظاهر و هم منطق را با کاتلین مینویسیم.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## روش اعلامی یا Declarative چیست؟
|
||||||
|
|
||||||
|
در روشهای قدیمی (Imperative)، ما باید خط به خط به سیستم دستور میدادیم که چطور دکمه را پیدا کند، رنگش را عوض کند و... اما در روش **Declarative (اعلامی)**، ما فقط توصیف میکنیم که صفحه در هر لحظه بر اساس دادههایی که دارد، **باید چه شکلی باشد**. شعار اصلی کامپوز این فرمول است:
|
||||||
|
|
||||||
|
$$UI = f(State)$$
|
||||||
|
|
||||||
|
یعنی رابط کاربری ($UI$) صرفاً یک تابع ($f$) از وضعیت دادههای برنامه ($State$) است. اگر داده تغییر کند، ظاهر برنامه خود به خود آپدیت میشود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش چهاردهم: اجزای اصلی Compose (Composable Functions)
|
||||||
|
|
||||||
|
در کامپوز، هر جزء از رابط کاربری یک تابع کاتلین است که بالای آن آنوتیشن `@Composable` قرار میگیرد. به این اجزا صراحتاً "کامپوزبل" میگوییم.
|
||||||
|
|
||||||
|
### Text
|
||||||
|
|
||||||
|
برای نمایش هرگونه متن روی صفحه استفاده میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Text("Hello")
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Button
|
||||||
|
|
||||||
|
یک دکمه قابل کلیک میسازد. کدهایی که باید هنگام کلیک اجرا شوند داخل بلاک `onClick` قرار میگیرند.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Button(onClick = { /* کدی که بعد از کلیک باید اجرا شود */ }) {
|
||||||
|
Text("Click Me") // محتوای داخل دکمه (میتواند متن یا تصویر باشد)
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Column (ستون)
|
||||||
|
|
||||||
|
یک لایوت اصلی است که اجزای داخلش را به صورت **عمودی** (زیر هم) میچیند.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Column {
|
||||||
|
Text("A")
|
||||||
|
Text("B") // کاملاً زیر کاراکتر A قرار میگیرد
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Row (ردیف)
|
||||||
|
|
||||||
|
یک لایوت اصلی است که اجزای داخلش را به صورت **افقی** (کنار هم) میچیند.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Row {
|
||||||
|
Text("A")
|
||||||
|
Text("B") // در سمت راست یا چپ کاراکتر A (بسته به جهت زبان) قرار میگیرد
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Spacer (فاصلهانداز)
|
||||||
|
|
||||||
|
یک المان نامرئی است که برای ایجاد فاصله دقیق بین اجزای صفحه (عمودی یا افقی) استفاده میشود. اندازه آن با واحد `dp` (Density-independent Pixels) مشخص میشود.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Spacer(modifier = Modifier.height(16.dp)) // ایجاد ۱۶ واحد فاصله عمودی
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش پانزدهم: Modifier (اصلاحکنندهها)
|
||||||
|
|
||||||
|
**Modifier**هاست که به اجزای کامپوز روح و شکل میدهند. مودیفایر یک شیء زنجیرهای است که همراه المانها فرستاده میشود تا رفتار، ظاهر، سایز، پسزمینه و حتی قابلیت کلیک شدن آن المان را تغییر دهد.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Text(
|
||||||
|
text = "Hello",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp) // ایجاد حاشیه داخلی ۱۶ دیپی
|
||||||
|
.background(Color.Blue) // تغییر رنگ پسزمینه به آبی
|
||||||
|
.fillMaxWidth() // پر کردن تمام عرض صفحه
|
||||||
|
)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
> **نکته:** ترتیب نوشتن دستورات در Modifier بسیار مهم است؛ مثلاً اگر ابتدا padding بنویسید و بعد background، حاشیه شما رنگ نمیگیرد، اما اگر برعکس بنویسید، حاشیه هم رنگی میشود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش شانزدهم: مدیریت State (وضعیت)
|
||||||
|
|
||||||
|
در کامپوز، ظاهر برنامه مستقیماً به دادهها وصل است. به دادهای که در طول زمان تغییر میکند و تغییر آن باید ظاهر برنامه را دگرگون کند، **State** میگوییم. برای اینکه کامپوز متوجه تغییرات یک متغیر شود، نمیتوان از یک متغیر عادی کاتلین استفاده کرد؛ بلکه باید از ابزارهای زیر استفاده کنیم:
|
||||||
|
|
||||||
|
* **`mutableStateOf(value)`:** این ابزار متغیر را به یک دادهی "دیدهباندار" یا رادیویی تبدیل میکند که کامپوز مدام گوشبهزنگِ تغییراتش است.
|
||||||
|
* **`remember`:** از آنجایی که توابع کامپوز مدام در حال بازخوانی هستند، اگر از `remember` استفاده نکنیم، مقدار متغیر با هر بار تازه شدن صفحه دوباره صفر یا ریست میشود! `remember` حافظه کوتاهمدت کامپوز است که مقدار قبلی متغیر را در حافظه نگه میدارد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مثال کاربردی State
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// تعریف یک متغیر وضعیت که مقدار اولیه آن ۰ است و در حافظه ماندگار میماند
|
||||||
|
var count by remember { mutableStateOf(0) }
|
||||||
|
|
||||||
|
Button(onClick = {
|
||||||
|
count++ // با هر بار کلیک، مقدار یک واحد زیاد میشود
|
||||||
|
}) {
|
||||||
|
Text("تعداد کلیکها: $count") // متن دکمه به صورت خودکار با تغییر متغیر آپدیت میشود
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# بخش هفدهم: Recomposition (بازسازماندهی)
|
||||||
|
|
||||||
|
وقتی که یک **State** (وضعیت) تغییر میکند، کامپوز متوجه این تغییر میشود و تابع Composable مربوطه را یکبار دیگر با مقدار جدید اجرا میکند تا ظاهر جدید صفحه را رسم کند. به این فرآیند اجرای مجدد، **Recomposition** میگویند.
|
||||||
|
|
||||||
|
یکی از شاهکارهای کامپوز این است که هوشمند عمل میکند; کل صفحه را دوباره از نو رندر نمیکند، بلکه **فقط و فقط** همان دکمه یا متنی که دادهاش تغییر کرده را دوباره میکشد و بقیه اجزای صفحه بدون تغییر باقی میمانند. این امر سرعت و بازدهی برنامه را به شدت بالا میبرد.
|
||||||
|
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user