├── .gitignore ├── LICENSE ├── README.md └── src ├── README.md ├── about-author └── README.md ├── about-this-book └── README.md ├── anko-and-extension-functions └── README.md ├── classes-and-functions └── README.md ├── creating-a-new-project └── README.md ├── data-classes └── README.md ├── getting-ready └── README.md ├── introduction └── README.md ├── is-this-book-for-you └── README.md ├── making-the-forecast-list-clickable └── README.md ├── operators-overloading └── README.md ├── parsing-data └── README.md ├── retrieving-data-from-api └── README.md ├── translator-talk └── README.md ├── variables-and-properties └── README.md └── writing-your-first-class └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | *.iml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kotlin Farsi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenSourceTutorials-Android 2 | 3 | [![Join the chat at https://gitter.im/KotlinFarsi/OpenSourceTutorials-Android](https://badges.gitter.im/KotlinFarsi/OpenSourceTutorials-Android.svg)](https://gitter.im/KotlinFarsi/OpenSourceTutorials-Android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | Pages of [Android Programming With Kotlin Language](https://kotlinfarsi.com/courses/) tutorial [In Progress] 6 | 7 | Are you tired of using an ancient, inexpressive and unsafe language to develop your Android apps? Do you cry out loud every time you see a Null Pointer Exception in your bug tracker? Then Kotlin is your solution! A language specifically created for Java developers, easy to learn, expressive, null safe and really intuitive. Your productivity will boost and your apps will become more robust. Learn Kotlin the easy way by example and discover the tricks that will make coding easier. And now, it's officially supported by Google! 8 | 9 | This tutorial provided based on Antonio Leiva book [Kotlin for Android Developers](https://antonioleiva.com/kotlin-android-developers-book/). I personaly recommend to get that book. 10 | 11 | another repo **[kotlin-for-android-developers](https://github.com/sinadarvi/kotlin-for-android-developers)** translated from [Japanese repo](https://github.com/wangjiegulu/kotlin-for-android-developers-zh) to english language. 12 | 13 | Full course of this tutorial and another kotlin tutorials are accessible for free in KotlinFarsi.com website 14 | 15 | ## How to contribute on OpenSourceTutorials 16 | 17 | - install [git](https://git-scm.com/downloads) on your system 18 | - make a clone from this repo 19 | - make your changes 20 | - make a pull request and we will consider and accept your pull request 21 | 22 | ## How to be an Writer on KotlinFarsi 23 | 24 | for being a writer or a teacher in KotlinFarsi website you should first send us your resume to this link and then we will review and accept your memebrship. 25 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # فهرست 4 | 5 | الف ) درباره این کتاب 6 | 7 | ب ) آیا این کتاب مناسب شماست؟ 8 | 9 | پ ) درباره نویسنده 10 | 11 | ت ) چند سخن مترجم 12 | 13 | **[1 - معرفی](./introduction/README.md)** 14 | 15 | [1.1 )‌ کاتلین چیست؟](./introduction/README.md#کاتلین-چیست) 16 | 17 | [1.2 ) با کاتلین به چه میرسیم؟](./introduction/README.md#با-کاتلین-به-چه-میرسیم) 18 | 19 | **[2 - آماده شدن](./getting-ready/README.md)** 20 | 21 | [2.1 ) اندروید استودیو](./getting-ready/README.md#اندروید-استودیو) 22 | 23 | [2.2 ) نصب پلاگین کاتلین](./getting-ready/README.md#نصب-پلاگین-کاتلین) 24 | 25 | **[3 - ساختن یک پروژه جدید](./creating-a-new-project/README.md)** 26 | 27 | [3.1 ) ساختن پروژه در اندروید استودیو](./creating-a-new-project/README.md#ساختن-پروژه-در-اندروید-استودیو) 28 | 29 | [3.2 ) تنظیمات گردل](./creating-a-new-project/README.md#تنظیمات-گردل) 30 | 31 | [3.3 ) تبدیل MainActivity به کد کاتلین](./creating-a-new-project/README.md#تبدیل-mainactivity-به-کد-کاتلین) 32 | 33 | [3.4 ) تست کارکردن همه اجزا](./creating-a-new-project/README.md#تست-کارکردن-همه-اجزا) 34 | 35 | **[4 - کلاس ها و توابع](./classes-and-functions/README.md)** 36 | 37 | [4.1 ) روش تعریف کلاس](./classes-and-functions/README.md#روش-تعریف-کلاس) 38 | 39 | [4.2 ) ارث بری](./classes-and-functions/README.md#ارث-بری) 40 | 41 | [4.3 ) توابع](./classes-and-functions/README.md#توابع) 42 | 43 | [4.4 ) کانستراکتور و پارامترها](./classes-and-functions/README.md#کانستراکتور-و-پارامترها) 44 | 45 | **[5 - نوشتن اولین کلاس](./writing-your-first-class/README.md)** 46 | 47 | [5.1 ) ساختن layout](./writing-your-first-class/README.md#ساختن-layout) 48 | 49 | [5.2 ) آداپتور Recycler](./writing-your-first-class/README.md#آداپتور-recycler) 50 | 51 | **[6 - مقادیر و خصیصه ها](./variables-and-properties/README.md)** 52 | 53 | [6.1 ) type های پایه ای](./variables-and-properties/README.md#تایپ-های-پایه-ای) 54 | 55 | [6.2 ) متغیر ها](./variables-and-properties/README.md#متغیر-ها) 56 | 57 | [6.3 ) خصیصه ها](./variables-and-properties/README.md#خصیصه-ها) 58 | 59 | **[7 - Anko و توابع الحاقی](./anko-and-extension-functions/README.md)** 60 | 61 | [7.1 ) Anko چیست؟](./anko-and-extension-functions/README.md#anko-چیست) 62 | 63 | [7.2 ) شروع به استفاده از Anko](./anko-and-extension-functions/README.md#شروع-به-استفاده-از-anko) 64 | 65 | [7.3 ) توابع الحاقی](./anko-and-extension-functions/README.md#توابع-الحاقی) 66 | 67 | **[8 - بدست آوردن دیتا با استفاده از API](./retrieving-data-from-api/README.md)** 68 | 69 | [8.1 ) انجام درخواست](./retrieving-data-from-api/README.md#انجام-درخواست) 70 | 71 | [8.2 ) انجام درخواست خارج از نخ اصلی](./retrieving-data-from-api/README.md#انجام-درخواست-خارج-از-نخ-اصلی) 72 | 73 | **[9 - کلاس های دیتا](./data-classes/README.md)** 74 | 75 | [9.1 ) توابع اضافی](./data-classes/README.md#توابع-اضافی) 76 | 77 | [9.2 ) کپی کردن کلاس دیتا](./data-classes/README.md#کپی-کردن-یک-کلاس-دیتا) 78 | 79 | [9.3 ) مپ کردن یک آبجکت به متغیرها](./data-classes/README.md#مپ-کردن-یک-شی-به-متغیرها) 80 | 81 | **[10 - تجزیه دیتا](./parsing-data/README.md)** 82 | 83 | [10.1 ) تبدیل JSON به کلاس های دیتا](./parsing-data/README.md#تبدیل-json-به-کلاس-های-دیتا) 84 | 85 | [10.2 ) شکل دادن به لایه ی domain](./parsing-data/README.md#شکل-دادن-به-لایه-ی-domain) 86 | 87 | [10.3 ) نمایش دیتا بر روی UI](./parsing-data/README.md#نمایش-دیتا-بر-روی-ui) 88 | 89 | **[11 - Overloading Operators](./operators-overloading/README.md)** 90 | 91 | [11.1 ) جدول اوپراتور ها](./operators-overloading/README.md#جدول-اوپراتور-ها) 92 | 93 | [11.2 ) یک مثال](./operators-overloading/README.md#یک-مثال) 94 | 95 | [11.3 ) عملگرها در توابع الحاقی](./operators-overloading/README.md#عملگرها-در-توابع-الحاقی) 96 | 97 | **[12 - تجزیه دیتا](./making-the-forecast-list-clickable/README.md)** 98 | 99 | 100 | 101 | 102 | 103 | <بقیه فصل ها در حال ترجمه است> 104 | -------------------------------------------------------------------------------- /src/about-author/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Android/8b7c60dc86a7b48c920ffb243d606f1d42a45b90/src/about-author/README.md -------------------------------------------------------------------------------- /src/about-this-book/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Android/8b7c60dc86a7b48c920ffb243d606f1d42a45b90/src/about-this-book/README.md -------------------------------------------------------------------------------- /src/anko-and-extension-functions/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Anko و توابع الحاقی 4 | 5 | ## Anko چیست؟ 6 | 7 | Anko یک کتابخونه قدرتمند توسعه یافته توسط شرکت JetBrains هه. هدف اصلیش تولید صفحات UI با استفاده از Code به جای فایل xml هه .این یک ویژگی خیلی جالبه که بهتون پیشنهاد میکنم امتحانش کنید ولی من توی این پروژه ازش استفاده نمیکنم.برای من استفاده از xml راحت تره ولی شما میتونین این روش رو پیش بگیرین. 8 | 9 | اگرچه این تنها ویژگی نیست که ما از این کتابخونه بدست میاریم.Anko شامل تعداد زیادی از خصیصه ها و توابعه که میتونه کار رو براتون راحت¬تر کنه.شما مثال¬های زیادی توی این دوره خواهین دید و سریعا متوجه خواهید شد که چه مشکلاتی رو این کتابخونه حل میکنه. 10 | 11 | ## شروع به استفاده از Anko 12 | 13 | قبل از اینکه جلوتر بریم بهتره از Anko برای خلاصه سازی کدهامون استفاده کنیم. همینطور که خواهید دید، زمانی که از Anko استفاده میکنیم، اون همیشه یک import رو به همراه نام اون خصیصه یا تابع که ازش استفاده میکنیم رو به فایل اضافه میکنه. به این دلیل که Anko از توابع الحاقی استفاده میکنه تا بتونه ویژگیهای جدید رو به محیطتون اضافه کنه. 14 | 15 | داخل کلاس `MainActivity` ما میتونیم از تابع ساده¬تری برای پیداکردن `RecyclerView` استفاده کنیم: 16 | 17 |
18 | 19 | ```kotlin 20 | val forecastList: RecyclerView = find(R.id.forecast_list) 21 | ``` 22 | 23 | بهتره که با این کتابخونه بیشتر آشنا شین چون که خیلی از توابع این کتابخونه میتونه کارهارو براتون راحت تر کنه. 24 | 25 |
26 | 27 | ## توابع الحاقی 28 | 29 | تابع الحاقی تابعیه که میتونه رفتار جدیدی رو به کلاس اضافه کنه، حتی زمانی که دسترسی به سورس کد اون کلاس نداشته باشیم. مزیت استفاده از این توابع توی کاتلین اینه که لازم نیست اون شی رو به عنوان یک آرگومان ورودی به تابع پاس بدیم.تابع الحاقی دقیقا طوری عمل میکنه انگار جزئی از کلاسه و ما حتی میتونیم خود اون کلاس رو با استفاده از `this` به تابعمون پاس بدیم! 30 | 31 | به عنوان مثال ما میتونیم یک `toast` درست کنیم که دیگه لازم نباشه `context` رو بهش پاس بدیم! و این میتونه توی `Activity` ها و `Service` ها مورد استفاده قراربگیره! 32 | 33 |
34 | 35 | ```kotlin 36 | fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { 37 | Toast.makeText(this, message, duration).show() 38 | } 39 | ``` 40 | 41 |
42 | 43 | به عنوان مثال وقتی میخوایم داخل Activity ازش استفاده کنیم : 44 | 45 |
46 | 47 | ```kotlin 48 | toast("Hello world!") 49 | toast("Hello world!", Toast.LENGTH_LONG) 50 | ``` 51 | 52 |
53 | 54 | البته که Anko یک تابع `Toast` به مانند همین تابع درست کرده.Anko توابع مختلفی برای هم `CharSequence` و هم `resource` درست کرده که از اونجا رشته رو بهش پاس بدین، همچنین توابعی برای `toast` های کوتاه و بلند هم درست کرده! 55 | 56 |
57 | 58 | ```kotlin 59 | toast("Hello world!") 60 | longToast(R.id.hello_world) 61 | ``` 62 | 63 |
64 | 65 | توابع الحاقی حتی میتونن روی خصیصه ها هم انجام بشن!مثال بعدی که میبینین درواقع یک تابع الحاقی پیاده شده برروی یک خصیصه است که به مانند توابع الحاقی معمولیه. اینجا ما `getter` و `setter` دلخواه خودمون رو نوشتیم 66 | 67 |
68 | 69 | ```kotlin 70 | public var TextView.text: CharSequence 71 | get() = getText() 72 | set(v) = setText(v) 73 | ``` 74 | 75 |
76 | 77 | توابع الحاقی در واقع کلاس اصلی رو تغییر نمیدن بلکه تنها یک static import به جاییه که ازش استفاده میشه. توابع الحاقی میتونه در هر کلاسی تعریف بشه، این میتونه تمرین خوبی باشه اگه یک دسته از توابع الحاقی مرتبط رو توی یک فایل ذخیره کنیم. 78 | 79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /src/classes-and-functions/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس ها و توابع 4 | 5 | کلاس ها در کاتلین ساختار خیلی ساده ای دارن و البته یکسری تفاوت¬ها بین جاوا و این زبون وجود داره که بهتره قبل از این که به برنامه نویسی اندروید ادامه بدیم کمی راجع بهشون بدونیم. در ضمن شما میتونین از سایت try.kotlinlang.org استفاده کنین و مثال هارو امتحان کنین، بدون این که پروژه ای بسازین 6 | 7 | 8 | ## روش تعریف کلاس 9 | 10 | 11 | اگه میخواین یک کلاس تعریف کنین، این عمل تنها با استفاده از کلیدواژه `class` انجام میشه، یک کلاس ساده به اینصورت تعریف میشه: 12 | 13 |
14 | 15 | ```kotlin 16 | class MainActivity{ 17 | 18 | } 19 | ``` 20 | 21 |
22 | 23 | کلاس ها سازنده های خاص خودشون رو دارن. بعدا میبینیم که برای بعضی مواقع نیاز به سازنده اضافه پیدا میکنیم و این عمل در کاتلین شدنیه، ولی بیشتر شرایط که باهاش روبرو میشیم یک سازنده نیاز مارو برطرف میکنه.پارامتر ها مستقیمن بعد از نام کلاس تعریف میشن و در ضمن اگه کلاسمون بدنه ای نداشته باشه نیازی به اکولاد هم نداره. 24 | 25 |
26 | 27 | ```kotlin 28 | class Person(name: String, surname: String) 29 | ``` 30 | 31 |
32 | 33 | بدنه سازنده کجا تعریف میشه ؟ شما میتونین با استفاده از بلاک `init` بدنه سازنده رو بنوسین: 34 | 35 |
36 | 37 | ```kotlin 38 | class Person(name: String, surname: String) { 39 | init { 40 | // … 41 | } 42 | } 43 | ``` 44 | 45 |
46 | 47 | ## ارث بری 48 | 49 | به صورت پیشفرض یک کلاس از Any ارث¬بری شده(مثل Object در جاوا) ولی ما میتونیم از کلاس¬های دیگه هم ارث¬بری کنیم.کلاس ها به صورت پیشفرض بسته اند( مثل final class در جاوا) بنابراین ما زمانی میتونیم از یک کلاس ارث¬بری کنیم که اون کلاس با کلیدواژه open یا abstract به صورت باز معرفی شده باشه. 50 | 51 |
52 | 53 | ```kotlin 54 | open class Animal(name: String) 55 | class Person(name: String, surname: String) : Animal(name) 56 | ``` 57 | 58 |
59 | فقط یک نکته: 60 | 61 | ترجمه نشده 62 | 63 | 64 |
65 | 66 | 67 |
68 | 69 | ## توابع 70 | 71 | توابع(متد ها در جاوا) توسط کلیدواژه fun معرفی میشن: 72 | 73 |
74 | 75 | ```kotlin 76 | fun onCreate(savedInstanceState: Bundle?) { 77 | 78 | } 79 | ``` 80 | 81 |
82 | 83 | اگر مقدار بازگشتی یک تابع مشخص نشه، اون تابع مقدار Unit برمیگردونه، به مانند void در جاوا با این تفاوت که اینجا Unit واقعا یک object هه. البته که میتونین هر تایپ دلخواهی رو به عنوان خروجی برگردونین. 84 | 85 |
86 | 87 | ```kotlin 88 | fun add(x: Int, y: Int) : Int { 89 | return x + y 90 | } 91 | ``` 92 |
93 | > نکته: نیازی *به نقطه ویرگول نیست!* همینطور که در مثال بالا دیدین، نیازی به استفاده از نقطه ویرگول در پایان جمله نیست. وقتی شما به این روش عادت کنید متجه میشین که خیلی توی وقتتون صرفه جویی میشه. 94 | 95 | 96 | 97 | اگر مقدار بازگشتی رو بتونیم توی یک خط بنویسیم میتونیم از شر آکولادها راحت شیم و کدمون رو خلاصه تر بنویسیم. 98 | 99 |
100 | 101 | ```kotlin 102 | fun add(x: Int, y: Int) : Int = x + y 103 | ``` 104 | 105 |
106 | 107 | ## کانستراکتور و پارامترها 108 | 109 | پارامتر ها در کاتلین کمی متفاوته، همینطور که میبینین اول نامش رو مینویسیم بعد تایپش. 110 | 111 |
112 | 113 | ```kotlin 114 | fun add(x: Int, y: Int) : Int { 115 | return x + y 116 | } 117 | ``` 118 | 119 |
120 | 121 | یکی از ویژگی¬های واقعا عالی کاتلین اینه که توابعمون میتونن به صورت دلخواه مقدار پیشفرض داشته باشن. به عنوان مثال این یک تابع سادس که میتونین توی هر activity تون داشته باشین: 122 | 123 |
124 | 125 | ```kotlin 126 | fun toast(message: String, length: Int = Toast.LENGTH_SHORT) { 127 | Toast.makeText(this, message, length).show() 128 | } 129 | ``` 130 | 131 |
132 | 133 | همینطور که میبینین پارامتر دوم (length) یک مقدار پیشفرض داره، به این معنی که شما میتونین برای پارامتر دوم مقدار داشته باشین یا نه که این از بازنویسی بیجای تابع جلوگیری کنه. 134 | 135 |
136 | 137 | ```kotlin 138 | toast("Hello") 139 | toast("Hello", Toast.LENGTH_LONG) 140 | ``` 141 | 142 |
143 | 144 | این مساویه کد جاوای زیره: 145 | 146 |
147 | 148 | ```java 149 | void toast(String message){ 150 | toast(message, Toast.LENGTH_SHORT); 151 | } 152 | 153 | void toast(String message, int length){ 154 | Toast.makeText(this, message, length).show(); 155 | } 156 | ``` 157 | 158 |
159 | 160 | حتی اگه بخواین میتونین این تابع رو پیچیده تر هم کنین: 161 | 162 |
163 | 164 | ```kotlin 165 | fun niceToast(message: String, 166 | tag: String = MainActivity::class.java.simpleName, 167 | length: Int = Toast.LENGTH_SHORT) { 168 | Toast.makeText(this, "[$tag] $message", length).show() 169 | } 170 | ``` 171 | 172 |
173 | 174 | در کاتلین شما حتی میتونین به پارامتر¬هایی که پاس میدین نام بدین و مشخص کنین چه مقداری رو به چه پارامتری دارین میدین. 175 | 176 |
177 | 178 | ```kotlin 179 | toast(message = "Hello", length = Toast.LENGTH_SHORT) 180 | ``` 181 | 182 |
183 | > نکته: *رشته های نمونه!* شما میتونین از نمونه ها برای رشته هاتون استفاده کنین. این کار رو زمانی که با یک رشته مشکل کار میکنین راحت تر میکنه.به عنوان مثال : `{Your name is ${user.name` 184 | 185 |
-------------------------------------------------------------------------------- /src/creating-a-new-project/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # ساختن یک پروژه جدید 4 | 5 | اگه تا حالا از اندروید استودیو و گردل استفاده کرده باشین این قسمت براتون ساده­یه . من نمیخوام خیلی اطلاعات زیادی یا اسکرین شاتی براتون بذارم، چون به مرور زمان UI تغییر میکنه و اون موقع این خط­ها معنی پیدا نمیکنن. 6 | 7 | 8 | ## ساختن پروژه در اندروید استودیو 9 | 10 | در اولین قدم اندروید استدیو رو باز کنین و روی دکمه Create New Project کلیک کنید. 11 | 12 | نیازمند تصویر 13 | 14 | اون ازتون میخواد که نام اپ رو وارد کنین. 15 | 16 | نیازمند تصویر 17 | 18 | بعد ازتون میپرسه که company Domain رو وارد کنین. چون شما این اپ رو منتشر نمیکنین، مهم نیست که چه عبارتی میخواین اونجا وارد کنین. و بعدش مشخص کنین که کجا میخواین اپتون رو ذخیره کنین 19 | 20 | نیازمند تصویر 21 | 22 | در مرحله بعد ازتون درباره کمترین مقدار API سوال میشه.ما API 15 رو انتخاب میکنیم چون یکی از لایبری هایی که ازش استفاده میکنیم حداقل API 15 رو داره.فعلا پلتفرم دیگه به غیر از Phone and Tablet رو انتخاب نکنین 23 | 24 | نیازمند تصویر 25 | 26 | و در انتها از ما خواسته میشه که یک نمونه پیش ساخته از activity که میخوایم رو انتخاب کنیم. بهتره که Empty Activity رو انتخاب کنیم چراکه بعدا میخوام در مورد یک ویژگی خاص پلاگین کاتلین صحبت کنم. 27 | 28 | نیازمند تصویر 29 | 30 | 31 | 32 | ## تنظیمات گردل 33 | 34 | پلاگین کاتلین شامل ابزار هایی میشه که تنضیمات gradle رو برامون انجام میدن ولی من ترجیح میدم که کنترلی بر چیزی که در فایل گردلم مینویسم داشته باشم در غیر این صورت ممکنه کمی بهم ریخته بشن. به هرصورت این ایده خوبیه که بدونیم چجوری کارها انجام میشن قبل از این که از ابزار های اتومات استفاده کنیم، بنابراین این دفعه دستی کارمون رو انجام میدیم. 35 | اولین کار اینه که فایل build.gradle امون رو پیدا کنیم که تقریبا میشه گفت شبیه اینه : 36 | 37 |
38 | 39 | ```groovy 40 | buildscript { 41 | ext.support_version = '23.1.1' 42 | ext.kotlin_version = '1.1.3' 43 | ext.anko_version = '0.8.2' 44 | repositories { 45 | jcenter() 46 | } 47 | dependencies { 48 | classpath 'com.android.tools.build:gradle:1.5.0' 49 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 50 | } 51 | } 52 | allprojects { 53 | repositories { 54 | jcenter() 55 | } 56 | } 57 | ``` 58 | 59 |
60 | 61 | همینطور که میبینین ما داریم یک متغیر ایجاد میکنیم که ورژن درحال حاظر کاتلینمون رو بگه. حتما چک کنید که این ورژن با ورژن در حال حاظر استفاده شما یکی باشه.سعی کنید همیشه از اخرین ورژن استفاده کنید.ما به این شماره ورژن در چندین جا نیاز داریم.به عنوان مثال وقتی که از kotlin standard library استفاده میکنیم باید مشخص کنیم که از چه ورژنی استفاده میشه. 62 | عین همین کار رو برای لایبری support و anko انجام میدیم.این بهمون این مزیت رو میده که از شماره ورژن­هامون هرجایی استفاده کنیم. 63 | ما بعدا وابستگی هایی مثل kotlin standard library و anko library رو مثل kotlin و kotlin android extensions رو به برناممون اضافه میکنیم. 64 | 65 |
66 | 67 | ```groovy 68 | apply plugin: 'com.android.application' 69 | apply plugin: 'kotlin-android' 70 | apply plugin: 'kotlin-android-extensions' 71 | android { 72 | … 73 | } 74 | dependencies { 75 | compile "com.android.support:appcompat-v7:$support_version" 76 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 77 | compile "org.jetbrains.anko:anko-common:$anko_version" 78 | } 79 | buildscript { 80 | repositories { 81 | jcenter() 82 | } 83 | dependencies { 84 | classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" 85 | } 86 | } 87 | ``` 88 | 89 |
90 | 91 | درواقع Anko یک کتابخونه است که با استفاده از قدرت Kotlin بعضی کارهارو برامن ساده­تر میکنه.این کتابخونه به چندین قسمت مختلف تقسیم شده تا اگر از قسمتی استفاده نمیکنیم الکی اونو به پروژه اضافه نکنیم. 92 | 93 | 94 | ## تبدیل MainActivity به کد کاتلین 95 | 96 | یکی از ویژگی های منحصر به فردی که همراه پلاگین کاتلین میاد اینه که میتونه فایل جاوا رو به فایل کاتلین تبدیل کنه. به مانند همه ی فرآیندهای اتومات این فرآیند عالی نیست ولی این خیلی میتونه کمکمون کنه، مخصوصا در روز اول که به زبون کاتلین عادت نکردیم. 97 | 98 | خب ما از این برای تبدیل فایل MainActivity.java مون به یک فایل کاتلین استفاده میکنیم. وقتی فایل رو باز کردین از قسمت بالا Code رو پیدا کنین و تقریبا اون آخرا دنبال Convert Java File to Kotlin File بگردین. پرسه انجام میشه و در انتها شما فایل کاتلین مورد نظرتون رو دارین. به تفاوت ها دقت کنین و با این زبون آشناتر بشین. 99 | 100 | 101 | ## تست کارکردن همه اجزا 102 | 103 | اول لازمه که به فایل `activity_main.xml` مراجعه کنین و یک `id` برای `TextView` تون انتخاب کنین. 104 | 105 |
106 | 107 | ```xml 108 | 113 | ``` 114 |
115 | 116 | حالا کافیه برگردین به MainActivity.java و در قسمت `()onCreate` این تغییرات رو بدین: 117 | 118 |
119 | 120 | ```kotlin 121 | override fun onCreate(savedInstanceState: Bundle?) { 122 | super.onCreate(savedInstanceState) 123 | setContentView(R.layout.activity_main) 124 | message.text = "Hello Kotlin!" 125 | } 126 | ``` 127 | 128 |
129 | 130 | به لطف همکاری کاتلین با جاوا ما میتونین متدهای `setter` و `getter` رو به صورت خصیصه ای انجام بدیم.حالا بعدا بیشتر درباره خصیصه¬ها صحبت میکنیم ولی اینجا اگه دقت کنین به جای `()message.setText` مستقیم مقدار جدید رو به `text` دادیم.درواقع کامپایلر خودش بعدا از متد جاوای واقعی استفاده میکنه و این عملکرد رو خراب نمیکنه! فقط خوبیش برای ما توسعه دهنده هاست که با راحتی بیشتر کارامون رو انجام میدیم. 131 | 132 | یک چیز دیگه هم فراموش کردم بهتون بگم.کو `findViewById` ایمون؟ کاتلین در واقع این اجازه رو میده که ما نیازی به Bind کردن کد جاوامون با فایل xml نداشته باشیم و به صورت مستقیم و با استفاده از `id` به اون کامپوننت دسترسی داشته باشیم. اینجا هم تنها کاری که لازم بود انجام بدیم اینه که message رو صدا بزنیم. 133 | 134 | حالا اگه برنامه رو اجرا کنیم متوجه خواهیم شد که برنامه به درستی کار میکنه و مقدار جدید رو نشون میده. 135 | 136 |
137 | 138 | -------------------------------------------------------------------------------- /src/data-classes/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس های دیتا 4 | 5 | کلاس های دیتا یکی از قدرتمندترین کلاس های کاتلین هستن که از نوشتن کدهای اضافی و بیهوده جلوگیری میکنن. 6 | 7 | POJO : کلاس هایی که برای نگه داشتن وضعیت به کار میرن و معمولا فعالیت های ساده ای رو انجام میدن. معمولا تنها توابع `getter` و `setter` ای مهیا میکنن که اجازه دسترسی به `field` هاشون رو میده. 8 | 9 | تعریف کلاس های دیتا در کاتلین واقعا به سادگی کد زیره : 10 | 11 |
12 | 13 | ```kotlin 14 | data class Forecast(val date: Date, val temperature: Float, val details: String) 15 | ``` 16 | 17 |
18 | 19 | ## توابع اضافی 20 | 21 | کلاس های دیتا یکسری توابع جالب در اختیارمون قرار میده و اینها همه جدا از دسترسی به خصیصه¬هاش هستن. 22 | * `equals()` : خصیصه¬های دو شی رو با هم مقایسه میکنه که ببینه برابر هستن یا نه. 23 | * `hashCode()` : hash-Code محاسبه شده از روی خصیصه هارو برمیگردونه. 24 | * `copy()` : میتونیم با استفاده از این یک شی رو به علاوه با خصیصه هاش کپی کنیم 25 | * تعدادی دیگه از توابع 26 | 27 | ## کپی کردن یک کلاس دیتا 28 | 29 | اگه ما از خاصیت مصون بودن استفاده کنیم نمیتونیم مقدارش رو عوض کنیم، مگر این که یک مقدار جدید بهش بدیم( منظور اینه که یک شی جدید ازش بسازین و بهش نسبت بدین) . توی کلاس های دیتا تابعی ظاهر شده به نام `copy()` که کارش کپی کردن از یک شی هه ولی یکی دیگه از خوبیاش اینه که شما هم میتونین از یک شی کپی بگیرین و هم مقدار جدید به جای خصیصه های دلخواهتون بذارین: 30 | 31 |
32 | 33 | ```kotlin 34 | val f1 = Forecast(Date(), 27.5f, "Shiny day") 35 | val f2 = f1.copy(temperature = 30f) 36 | ``` 37 | 38 |
39 | 40 | الان ما با استفاده از این تابع دیتای شی اول رو کپی کردیم و تنها مقدار `temperature` رو عوض کردیم، بدون این که مقدار بقیه حالت ها و شی اول عوض شه ! 41 | 42 | ## مپ کردن یک شی به متغیرها 43 | 44 | این روند به نام multi-declaration انجام میگیره و به معنی مپ کردن هر خصیصه داخل یک شی به یک متغیره. (اگر دقت کرده باشین، در هنگام استفاده از شی ها، توابعی به نام `ComponentX` وجود دارن که به صورت اتومات ساخته میشن و دلیل ساخته شدنشون هم همینه). به مثال زیر دقت کنین: 45 |
46 | 47 | ```kotlin 48 | val f1 = Forecast(Date(), 27.5f, "Shiny day") 49 | val (date, temperature, details) = f1 50 | ``` 51 | 52 |
53 | 54 | این multi-declaration به کد های زیر کامپایل میشه: 55 | 56 |
57 | 58 | ```kotlin 59 | val date = f1.component1() 60 | val temperature = f1.component2() 61 | val details = f1.component3() 62 | ``` 63 | 64 |
65 | 66 | ایده پشت این ویژگی خیلی قدرتمنده و میتونه توی خلاصه سازی کدمون توی شرایط مختلف کمک کنه. به عنوان مثال کلاس Map یکسری توابع الحاقی داره که پیاده سازی شده تا بتونن کلیدها و مقادیر اون هارو شناسایی کنن: 67 | 68 |
69 | 70 | ```kotlin 71 | for ((key, value) in map) { 72 | Log.d("map", "key:$key, value:$value") 73 | } 74 | ``` 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/getting-ready/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # آماده شدن 4 | 5 | خب حالا که فهمیدید چه کارهایی میشه با کاتلین انجام داد، من مطمئنم شما منتظر اینین که هرچه زودتر در عمل ازش استفاده کنین. نگران نباشید، بخش های ابتدایی این دوره بهتون کمک میکنه که چطور محیط توسعه اتون رو برای کاتلین تنظیم کنین تا بتونین هرچه زودتر شروع به کدزنی کنین. 6 | 7 | 8 | 9 | ## اندروید استودیو 10 | 11 | اولین چیزی که مسلما نیازدارین اینه که اندروید استودیو رو نصب کرده باشین. همینطور که میدونین اندروید استودیو یک محیط توسعه رسمی برای اندرویده که از سال 2013 به صورت پیشنمایشی و سال 2014 به صورت نهایی درمعرض استفاده قرارگرفت. 12 | 13 | اندروید استودیو به صورت پلاگین برروی IntelliJ IDEA پیاده سازی شد. IDEA یک محیط توسعه جاواست که توسط شرکت JetBrains ساخته شده.همین شرکت سازنده Kotlin هم هست و همینطور که میبینین همه­ی این­ها با هم ارتبط دارن. 14 | 15 | قبول کردن اندروید استدیو به عنوان محیط توسعه نرم­افزاری یکی از مهم­ترین قدم هایی بود که توسعه دهندگان اندروید برداشتن، اول به این دلیل که محیط باگ دار Eclipse رو ترک کردن و به سمت محیطی رفتن که مخصوص توسعه­دهندگان جاوا طراحی شده بود.ما امروزه از خیلی از ویژگی های این محیط مثل هوشمندی، سرعت، تکمیل کد ، آنالیز کدش لذت و استفاده می­بریم. 16 | 17 | و دلیل دوم به خاطر Gradle بود، چراکه به عنوان یک Build System رسمی برای اندروید شناخته شده بود که خیلی از امکانات جدید مربوط به version Building و deploy رو ممکن کرده بود. دوتا از امکانات جذاب Gradle یکی build systems و دیگری flavours هه که این امکان رو بهمون میده که به تعداد زیادی از یک بیس کد، اپ های مختلف توسعه بدیم. 18 | 19 | اگه هنوز از Eclipse استفاده میکنین، متاسفانه برای این که تا پایان این دوره همراهمون باشین نیازه که به Android­ Studio سویچ کنین.تیم توسعه­دهنده کاتلین برای Eclipse هم پلاگینی درست کردن ولی خب مسلما همیشه نسبت به اندروید استودیه عقب خواهد بود و مطمئنن طولی نخواهد کشید که متوجه بشین چه چیزهایی رو دارین ازدست میدین به محض این که استفاده ازش رو شروع کنین. 20 | 21 | هدف این دوره استفاده از Android Studio و Gradle نیست ولی اگر از این ابزار­ها استفاده نکردین، نگران نباشین. من مطمئنم که شما میتونین در این بین چیزهایی رو یادبگیرین و همراه این دوره باشین. 22 | 23 | 24 | 25 | ## نصب پلاگین کاتلین 26 | 27 | از IntelliJ 15 پلاگین کاتلین به صورت نصب شده برروی IDEA ارائه میشه، این ممکنه که Android Studio شما هنوز این پلاگین رو نداشته باشه و لازم باشه که شما به قسمت Plugins در خود استودیو مراجعه کنین و این پلاگین رو نصب کنین. 28 | 29 | حالا محیط شما اماده شده تا بدون یک ذره تفاوت نسبت به جاوا ، این زبون رو بفهمه ، کامپایل و اجرا کنه. 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/introduction/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # معرفی 4 | شما متوجه شدین که جاوا 7 منسوخه و شما سزاوار یک زبون مدرن تری هستین. تبریک میگم. همینطور که شما میدونید حتی با وجود اینکه جاوا 8 اون بیرونه و بهبودهای زیادی که از یک زبون مدرن انتظار میره رو در خودش شامل شده ما توسعه دهنده های اندروید مجبوریم از جاوا 7 استفاده کنیم و این به خاطر مسائل قانونیه. ولی حتی اگه این محدودیت نبود و دستگاه های اندرویدی جدیدی که به بازار میومدن قادر به اجرای جاوا 8 باشن، باز هم نمیتونستیم از جاوا 8 استفاده کنیم تا زمانی که دستگاه های در حال حاظر وجود دارن منسوخ بشن و هیچ کسی ازشون استفاده نکنه. بنابراین من متاسفانه این لحظه رو نزدیک نمیبینم. 5 | ولی همه چیز که ازدست نرفته! خوشبختانه به دلیل استفاده از Java Virtual Machine ما میتونیم برنامه های اندرویدی بنویسیم که از بایت کد های کامپایل شده از زبون دیگه استفاده کنه و در نتیجه JVM میتونه اون هارو بفهمه. 6 | همینطور که شما میتونین تصور کنین گزینه های زیادی مثل Groovy, Scala, Clojure و البته Kotlin اون بیرونه. البته در حال حاظر بعضیاشون قابل استفاده ان. 7 | 8 | ترجمه نشده 9 | 10 | 11 | ## کاتلین چیست؟ 12 | 13 | 14 | کاتلین همینطور که توضیح داده شد یک زبون بر پایه JVM هه که JetBrains کمپانی سازنده IntelliJ IDEA اونو ساخته و البته که Android Studio هم برپایه IntelliJ IDEA ساخته شده. 15 | 16 | دو ویژگی زبون کاتلین که برای توسعه دهنده های اندروید جذابش میکنه: 17 | 18 | 1. **کاتلین خیلی ملموسه و به راحتی قابل یادگیری برای توسعه دهنده های اندرویده**. بخش های زیادی از این زبون خیلی مشابه اون چیزاییه که شما میدونیده و بخش های پایه ای متفاوت رو میتونین به راحتی یاد بگیرین. 19 | 20 | 2. **یکپارچگی کامل با** **IDE** **که هر روزه باهاش کار میکنیم**. Android Studio میتونه کد کاتلین رو بفهمه، کامپایل و اجرا کنه و ساپورت برای این زبون از طرف کمپانی میاد که این IDE رو توسعه میدن، پس ما توسعه دهنده های اندروید اولین کسانی هستیم که از تغییرات باخبر میشیم. 21 | 22 | این تنها مربوط به این میشه که این زبون چگونه با ابزار هامون همکاری میکنه ولی برتری های این زبون نسبت به جاوا 7 چیه ؟ 23 | 24 | - **رسا و واضح تره** **:** این یکی از ویژگی های مهم این زبونه. شما میتونین با مقدار کمی کد زدن منظور خودتون رو بیان کنید. 25 | 26 | - **امن تره**: این زبون null safe هه. به این معنی که اگر در زمان کامپایل به یک موقعیت که احتمال null بودنش وجود داره بر بخوریم باید مشخص کنیم که چه کاری رو باید انجام بده تا زمان اجرا به Exception نخوریم.ما باید مشخص کنیم که آیا یک شی میتونه null باشه یا نه که این زمان زیادی از دیباگ ما رو کم میکنه. 27 | 28 | - **یک زبون** **functional** **هه** :کاتلین یک زبون شی گراست و البته به مانند زبون های مدرن از تعدادی از ویژگی های زبون های functional استفاده میکنه. مثلا عبارت لاندا که توی بعضی مشکلات کمکمون میکنه و به راحتی مشکلمون رو رفع میکنه. یکی از ویژگی های جالب این زبون طریقه تعاملش با کالکشن هاست. 29 | 30 | - **از توابع الحاقی استفاده میکنه**: به این معنی که من اگر به سورس کد یک کلاس دسترسی نداشته باشم( که خیلی پیش میاد) میتونم به راحتی تابع هایی بنویسم که به اون کلاس الحاق شه. 31 | 32 | - **قابلیت همکاری با جاوا رو داره**: شما میتونین به استفاده از لایبری هایی که در زبون جاوا نوشته شده ادامه بدین، به این دلیل که همکاری بین این دو زبون فوقالعاده است. شما میتونین هم از جاوا در کاتلین استفاده کنین و هم از کاتلین در جاوا 33 | 34 | 35 | 36 | ## با کاتلین به چه میرسیم؟ 37 | 38 | بدون این که بیشتر توی زبون کاتلین غرق بشیم ( ما همه چیز رو توی این دوره یاد میگیریم ) لازمه به چند ویژگی که توی کاتلین هست و در جاوا کمبودش احساس میشه اشاره کنیم: 39 | 40 | **یک زبون رسا** 41 | 42 | با کاتلین شما میتونین با مقدار کمی از کد تموم مقصودی که میخواین رو برسونین و از خیلی از ویژگی های پیشفرض زبون جاوا راحت بشین. به عنوان مثال توی جاوا اگه میخواستیم یک bean و یا یک کلاس دیتا بسازیم لازم بود همه ی این کد هارو بنویسیم: 43 |
44 | 45 | ```java 46 | public class Artist { 47 | private long id; 48 | private String name; 49 | private String url; 50 | private String mbid; 51 | 52 | public long getId() { 53 | return id; 54 | } 55 | 56 | public void setId(long id) { 57 | this.id = id; 58 | } 59 | 60 | public String getName() { 61 | return name; 62 | } 63 | 64 | public void setName(String name) { 65 | this.name = name; 66 | } 67 | 68 | public String getUrl() { 69 | return url; 70 | } 71 | 72 | public void setUrl(String url) { 73 | this.url = url; 74 | } 75 | 76 | public String getMbid() { 77 | return mbid; 78 | } 79 | 80 | public void setMbid(String mbid) { 81 | this.mbid = mbid; 82 | } 83 | 84 | @Override 85 | public String toString() { 86 | return "Artist{" + 87 | "id=" + id + 88 | ", name='" + name + '\'' + 89 | ", url='" + url + '\'' + 90 | ", mbid='" + mbid + '\'' + 91 | '}'; 92 | } 93 | } 94 | ``` 95 | 96 |
97 | 98 | ولی توی کاتلین تنها کدی که باید بزنین که همین مقصود رو برسونه اینه : 99 | 100 |
101 | 102 | 103 | ```kotlin 104 | data class Artist(var id: Long, var name: String, var url: String, var mbid: String) 105 | ``` 106 | 107 | 108 |
109 | 110 | تنها یک خط کاملا بیانگر تموم خط کد هایی که اون بالا نوشتیم. در حالت عادی در یک کلاس نیازی به وجود getter و setter نداریم و با اضافه کردن کلیدواژه "data" استفاده از توابعی به مانند toString(),hashCode() و equals() رو برامون ممکن میساره! بدون این که یک خط کد بنویسیم. والبته که میتونیم اون هارو با override کردن به تابع دلخواه خودمون دربیاریم. 111 | 112 | **Null Safety** 113 | 114 | هنوز معادل فارسی درستی برای این مفهوم پیدا نکردم که بتونه درواژه مفهوم رو بیان کنه. در کاتلین مفهوم null وجود نداره! البته نه به این معنا که واقعا وجود نداره، به این معنی که تایپ ها نمیتونن null باشن، و اگر بخوان مقدار null به خودشون بگیرن باید مشخص بشن که null هستند. خب البته ما زمانی که اندروید رو توسعه میدیم باید هواسمون باشه که همونطور که گفتیم بسیاری از کتابخانه هامون جاوا هستند و جاوا این دفاع رو در خودش نداره. پس زمان کدنویسی با استفاده از عملگر`?` مشخص میکنیم که ایا در زمان اجرا این مقدار null خواهد بود یا نه . با این کد بیشتر متوجه خواهید شد: 115 |
116 | 117 | 118 | ```kotlin 119 | // This won't compile. Artist can't be null 120 | var notNullArtist: Artist = null 121 | // Artist can be null 122 | var artist: Artist? = null 123 | // Won't compile, artist could be null and we need to deal with that 124 | artist.print() 125 | 126 | // Will print only if artist != null 127 | artist?.print() 128 | // Smart cast. We don't need to use safe call operator if we previously 129 | // checked nullity 130 | if (artist != null) { 131 | artist.print() 132 | } 133 | // Only use it when we are sure it's not null. Will throw an exception otherwise. 134 | artist!!.print() 135 | // Use Elvis operator to give an alternative in case the object is null. 136 | val name = artist?.name ?: "empty" 137 | ``` 138 | 139 | 140 |
141 | 142 | **توابع الحاقی** 143 | 144 | ما با استفاده از این ویژگی میتونیم توابع جدید رو به هر کلاسی اضافه کنیم. خیلی پیش میومد که دلتون میخواست توابع جدیدی رو به کلاس هایی اضافه کنید که بهشون دسترسی نداشتید. به عنوان مثال خیلی خوبه که بتونین یک toast رو به یک fragment اضافه کنید: 145 | 146 |
147 | 148 | ```kotlin 149 | fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { 150 | Toast.makeText(getActivity(), message, duration).show() 151 | } 152 | ``` 153 | 154 |
155 | 156 | و حالا کافیه این کار رو انجام بدین: 157 | 158 |
159 | 160 | ```kotlin 161 | fragment.toast("Hello world!") 162 | ``` 163 | 164 |
165 | **پشتیبانی فانکشنال(لاندا ها)** 166 | 167 | چی می شد به جای استفاده از یک کلاس بی نام، اونم هر دفعه برای یک click listener تنها میگفتیم چه کاری میخوایم انجام بدیم؟ خوشبختانه به لطف لاندا ما حالا میتونیم از خیلی از ویژگی های خسته کننده جاوا راحت بشیم: 168 | 169 |
170 | 171 | ```kotlin 172 | view.setOnClickListener { toast("Hello world!") } 173 | ``` 174 | 175 |
176 | 177 | این ها تنها گزینه های کوچیکی بودن از چیز هایی که کاتلین میتونه انجام بده. در قسمت بعدی میخوایم عملی وارد استفاده از کاتلین بشیم. 178 | 179 | 180 | -------------------------------------------------------------------------------- /src/is-this-book-for-you/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Android/8b7c60dc86a7b48c920ffb243d606f1d42a45b90/src/is-this-book-for-you/README.md -------------------------------------------------------------------------------- /src/making-the-forecast-list-clickable/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # قابل کلیک سازی لیست پیشبینی 4 | 5 | 6 | آیتم های فعلی لیوت مون نیاز به مقداری کار داره تا برای اپ واقعی اماده بشه. اولین کار ساختن یک Xml مناسب با نیاز های ابتداییمونه. ما میخوایم یک آیکون، یک date و یک توضیحات به علاوه بالا و پایین بودن دما رو نشون بدیم. خب پس شروع میکنیم به ساختن لیوت `item_forecast.xml` : 7 | 8 |
9 | 10 | ```xml 11 | 12 | ``` -------------------------------------------------------------------------------- /src/operators-overloading/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Overloading Operators 4 | 5 | کاتلین تعداد مشخصی از آوپراتور های نمادین دارد که میتونیم به راحتی بر روی هر کلاسی استفاده کنیم. روشش هم ایجاد یک تابع با نام رزرو شده و مپ کردن اون به سمبله. Overload کردن این اوپراتور ها ساده نویسی و خانایی کد رو بیشتر کنه. 6 | 7 | اگر بخوایم کامپایلر رو آگاه کنیم که یک اوپراتور رو میخوایم overload کنیم، باید اون تابع رو با اصلاح کننده `operator` مشخص کنیم. 8 | 9 | ## جدول اوپراتور ها 10 | 11 | در جدول زیر هم میتونید یک سری از جدول ها رو ببینید که شامل اوپراتورها و دستور العمل های مطابق آن است. یک تابع که پیاده سازی شده باشد برای استفاده از آن اوپراتور در کلاس مشخص نیاز است. 12 | 13 |
14 | 15 | **Unary Operations** 16 | 17 | | | | 18 | |----------------|-------------------------------| 19 | |`+a` |`a.unaryPlus()` | 20 | |`-a` |`a.unaryMinus()` | 21 | |`!a` |`a.not()` | 22 | |`a++` |`a.inc()` | 23 | |`a--` |`a.dec()` | 24 | 25 | 26 | **Binary Operations** 27 | 28 | | | | 29 | |----------------|-------------------------------| 30 | |`a + b` |`a.plus(b)` | 31 | |`a - b` |`a.minus(b)` | 32 | |`a * b` |`a.times(b)` | 33 | |`a / b` |`a.div(b)` | 34 | |`a % b` |`a.mod(b)` | 35 | |`a..b` |`a.rangTo(b)` | 36 | |`a in b` |`b.contains(a)` | 37 | |`a !in b` |`!b.contains(a)` | 38 | |`a += b` |`a.plusAssign(b)` | 39 | |`a -= b` |`a.minusAssign(b)` | 40 | |`a *= b` |`a.timesAssign(b)` | 41 | |`a /= b` |`a.divAssign(b)` | 42 | |`a %= b` |`a.modAssign(b)` | 43 | 44 | **Array-like operations** 45 | 46 | | | | 47 | |-----------------------|-------------------------------| 48 | |`a[i]` |`a.get(i)` | 49 | |`a[i, j]` |`a.get(i, j)` | 50 | |`a[i_1,..., i_n]` |`a.get(i_1,..., i_n)` | 51 | |`a[i] = b` |`a.set(i, b)` | 52 | |`a[i, j] = b` |`a.set(i, j, b)` | 53 | |`a[i_1,..., i_n] = b` |`a.set(i_1, …, i_n, b)` | 54 | 55 | 56 | **Equals operation** 57 | 58 | | | | 59 | |-----------------------|------------------------------------| 60 | |`a == b` |`a?.equals(b) ?: b === null` | 61 | |`a != b` |`!(a?.equals(b) ?: b === null)` | 62 | 63 | 64 | 65 | 66 |
67 | عملگرهای `equals` مقداری متفاوتند، زیرا برای بهتر چک کردن تساوی از ترجمه ی پیچیده تری استفاده میکند که در نتیجه تابع باید دقیقا به صورت زیر پیاده سازی شود. 68 | 69 |
70 | 71 | ````kotlin 72 | operator fun equals(other: Any?): Boolean 73 | ```` 74 | 75 | **Function invocation** 76 | 77 | | | | 78 | |-----------------------|------------------------------------| 79 | |`a(i)` |`a.invoke(i)` | 80 | |`a(i, j)` |`a.invoke(i, j)` | 81 | |`a(i_1, …, i_n)` |`a.invoke(i_1,..., i_n)` | 82 | 83 |
84 | 85 | ## یک مثال 86 | 87 | همانطور که تصور میکنید لیست های کاتلینی عملگرهای array-like ای به مانند بالا که گفته شده را دارا میباشد که در نتیجه به مانند جاوا میتونیم به آیتم های یک لیست دسترسی داشته باشیم ولی این تنها به این محدود نمیشود و در لیست های mutable (تغییرپذیر)، هر آیتم میتونه به صورت مستقیم مقدار دهی بشه. 88 | 89 |
90 | 91 | ```kotlin 92 | val x = myList[2] 93 | myList[2] = 4 94 | ``` 95 | 96 |
97 | 98 | اگر به یاد داشته باشید، کلاس دیتایی به نام `ForecastList` داشتیم که تشکیل شده از یک لیست با مقداری اطلاعات اضافی بود. اگه به جای این که درخواستی به لیست های داخلی برای بدست آوردن یک آیتم از اون بکنیم، به آیتم ها مستقیما دسترسی داشته باشیم، جالب تر خواهد بود. در ضمن، یک تابع به نام `size()` رو هم پیاده سازی میکنیم که آداپتور فعلی را ساده تر خواهد کرد. 99 | 100 |
101 | 102 | ```kotlin 103 | data class ForecastList(val city: String, val country: String, 104 | val dailyForecast: List) { 105 | operator fun get(position: Int): Forecast = dailyForecast[position] 106 | fun size(): Int = dailyForecast.size 107 | } 108 | ``` 109 | 110 |
111 | 112 | که این `onBindViewHolder` امون رو رو مقداری ساده تر خواهد کرد. 113 | 114 |
115 | 116 | ```kotlin 117 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 118 | with(weekForecast[position]) { 119 | holder.textView.text = "$date - $description - $high/$low" 120 | } 121 | } 122 | ``` 123 | 124 |
125 | 126 | همچنین `getItemCount()` نیز: 127 | 128 |
129 | 130 | ```kotlin 131 | override fun getItemCount(): Int = weekForecast.size() 132 | ``` 133 |
134 | 135 | ## عملگرها در توابع الحاقی 136 | 137 | لازم نیست که به کلاس های خودمون بسنده کنیم و میتونیم کلاس هامون رو با استفاده از توابع الحاقی گسترش بدیم. به عنوان مثال میتونیم مثل روش دستیابی به لیست ها، به `ViewGroup` هامون هم دستیابی داشته باشیم: 138 | 139 |
140 | 141 | ```kotlin 142 | operator fun ViewGroup.get(position: Int): View 143 | = getChildAt(position) 144 | ``` 145 | 146 |
147 | 148 | حالا میتونیم خیلی ساده `View` مورد نظر رو از `ViewGroup` با استفاده از `position` به دست بیاریم. 149 | 150 |
151 | 152 | ```kotlin 153 | val container: ViewGroup = find(R.id.container) 154 | val view = container[2] 155 | ``` 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /src/parsing-data/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # تجزیه دیتا 4 | 5 | ## تبدیل JSON به کلاس های دیتا 6 | 7 | حالا که میدونیم چگونه کلاس های دیتا را درست کنیم، آماده ی شروعِ تجزیه اطلاعات هستیم. در پکیج `data`، فایلی به نام `ResponseClasses.kt` ایجاد کنید. به وسیله `url` ای که در بخش 8 استفاده کردیم میتوانید ساختار فایل `json` رو ببینید که تشکیل شده از یک object است که یک شهر را داخل خودش دارد و یک لیست از پیشبینی ها. شهر یک `id` ، یک `name` ، مختصات و این که متعلق به چه کشوری هست نیز را دارا میباشد. هر پیشبینی به همراه اطلاعاتی مانند `date` و دماهای متفاوت و همچنین یک object از آب و هوا را داراست، که اون آبجکت توضیحات و همچنین یک `id` از یک `icon` رو به همراه خودش داره. 8 | 9 | 10 |
11 | 12 | ```kotlin 13 | data class ForecastResult(val city: City, val list: List) 14 | 15 | data class City(val id: Long, val name: String, val coord: Coordinates, 16 | val country: String, val population: Int) 17 | 18 | data class Coordinates(val lon: Float, val lat: Float) 19 | 20 | data class Forecast(val dt: Long, val temp: Temperature, val pressure: Float, 21 | val humidity: Int, val weather: List , 22 | val speed: Float, val deg: Int, val clouds: Int, 23 | val rain: Float) 24 | 25 | data class Temperature(val day: Float, val min: Float, val max: Float, 26 | val night: Float, val eve: Float, val morn: Float) 27 | 28 | data class Weather(val id: Long, val main: String, val description: String, 29 | val icon: String) 30 | ``` 31 | 32 |
33 | 34 | همینطور که از Gson برای تجزیه به کلاس هامون استفاده کردیم، باید در نظر داشته باشیم که خصیصه ها باید هم نامِ یکی های خود در فایل json باشند یا یک نام serialized شده را معرفی کنند. یکی از روش هایی که در اکثر معماری های برنامه نویسی توضیح داده میشود، استفاده از مدل های متفاوت برای لایه های متفاوت به جهت مجزا سازی آنها در برنامه امان است. بنابراین من ترجیح میدهم که کلاس ها را به صورت ساده declare کنم، به این دلیل که من آنها را قبل از این که در بقیه برنامه استفاده شوند تبدیل خواهم کرد. نام های خصیصه ها در اینجا دقیقا به مانند نام های موجود در json پاسخ داده شده است. 35 | 36 | حالا، کلاس `Request` برای برگرداندن جواب تجزیه شده نیاز به تغییرات دارد. همچنین برای خوانایی بیشتر، تنها نیاز به `zipcode` شهر دارد و از `url` کامل استفاده نخواهد شد. پس فعلا `static url` را به `companion object` خواهیم داد چون که شاید بعدا برای درخواست های بیشتر نیازی به آن پیدا کنیم. 37 | 38 | * `Companion object` ها: کاتلین اجازه میده که ابجکت هایی رو تعریف کنیم که رفتار `static` طوری داشته باشند. ما نمیتونیم خصیصه ها و یا توابعی `static` درست کنیم، پس باید به object ها روی بیاریم. اگرچه این کار نحوه پیاده سازی Singleton را ساده تر خواهند کرد. اگر به تعدادی خصیصه، `constant` و یا توابع `static` در کلاس نیاز داشته باشیم، از `companion object` استفاده میکنیم. این ابجکت در سرتاسر نسل های ساخته شده از کلاس قابل اشتراک گذاری است، دقیقا به مانند static در جاوا. 39 | 40 | به کد نتیجه گیری شده زیر نگاه کنید: 41 | 42 |
43 | 44 | ```kotlin 45 | class ForecastRequest(val zipCode: String) { 46 | 47 | companion object { 48 | private val APP_ID = "15646a06818f61f7b8d7823ca833e1ce" 49 | private val URL = "http://api.openweathermap.org/data/2.5/" + 50 | "forecast/daily?mode=json&units=metric&cnt=7" 51 | private val COMPLETE_URL = "$URL&APPID=$APP_ID&q=" 52 | } 53 | 54 | fun execute(): ForecastResult { 55 | val forecastJsonStr = URL(COMPLETE_URL + zipCode).readText() 56 | return Gson().fromJson(forecastJsonStr, ForecastResult::class.java) 57 | } 58 | } 59 | ``` 60 | 61 |
62 | 63 | فراموش نکنید که کتابخانه Gson را به `build.gradle` اضافه کنید 64 | 65 |
66 | 67 | ```groovy 68 | compile "com.google.code.gson:gson:2.4" 69 | ``` 70 | 71 |
72 | 73 | ## شکل دادن به لایه ی `domain` 74 | 75 | حالا نوبت ساختن پکیج نمایش دهنده ی لایه ی `domain` هه که شامل چند `command` هه! ولی برای شروع اول باید `command` رو تعریف کنیم. 76 | 77 |
78 | 79 | ```kotlin 80 | public interface Command { 81 | fun execute(): T 82 | } 83 | ``` 84 | 85 |
86 | 87 | این دستورات (`command`) یک فعالیت رو اجرا میکنن و یک آبجکت رو که جنس کلاسش به صورت `generic type` مشخص شده رو برمیگردونن. یکی از ویژگی های جالب اینه که هر تابعی در کاتلین یک مقدار برمیگردونه! به صورت پیشفرض، اگر جنس مقداری که برگردانده خواهد شد مشخص نبود، یک آبجکت از جنس کلاس `Unit` رو برمیگدونه. بنابراین اگر میخوایم که `command` مون چیزی برنگردونه، میتونیم جنسش رو `Unit` نیز معرفی کنیم. 88 | 89 | `Interface` ها در کاتلین، قدرتمند تر از جاوا هستند چون میتونن شامل کد هم بشن ولی برای فعلا ما کاری به این ویژگی نداریم. در فصل های آینده بیشتر در مورد این موضوع توضیح خواهیم داد. 90 | 91 | در دستور اول، نیازه که اول پیشبینی رو از API درخواست کنیم و بعد به کلاس `domain` تبدیل کنیمش. کد کلاس های `domain` رو در زیر ببینیم : 92 | 93 | 94 |
95 | 96 | ```kotlin 97 | data class ForecastList(val city: String, val country: String, 98 | val dailyForecast:List) 99 | data class Forecast(val date: String, val description: String, val high: Int, 100 | val low: Int) 101 | ``` 102 | 103 |
104 | 105 | حالا احتمالا این کلاس ها رو بعدا وقتی ویژگی های دیگه ای اضافه شد، بازدید میکنیم ولی فعلا برای دیتایی که میخوایم نگه داریم کافیه. 106 | 107 | کلاس ها باید از `data` به مدل `domain` مپ بشن، بنابراین فعالیت بعدی ساخت `DataMapper` اهه. 108 | 109 | 110 |
111 | 112 | ```kotlin 113 | public class ForecastDataMapper { 114 | 115 | fun convertFromDataModel(forecast: ForecastResult): ForecastList { 116 | return ForecastList(forecast.city.name, forecast.city.country, 117 | convertForecastListToDomain(forecast.list)) 118 | } 119 | 120 | private fun convertForecastListToDomain(list: List): 121 | List { 122 | return list.map { convertForecastItemToDomain(it) } 123 | } 124 | 125 | private fun convertForecastItemToDomain(forecast: Forecast): ModelForecast { 126 | return ModelForecast(convertDate(forecast.dt), 127 | forecast.weather[0].description, forecast.temp.max.toInt(), 128 | forecast.temp.min.toInt()) 129 | } 130 | 131 | private fun convertDate(date: Long): String { 132 | val df = DateFormat.getDateInstance(DateFormat.MEDIUM, 133 | Locale.getDefault()) 134 | return df.format(date * 1000) 135 | } 136 | } 137 | ``` 138 | 139 |
140 | 141 | در این حین که داریم از دو کلاس با نام های یکسان استفاده میکنیم، باید به یکی، نام مشخص و مجزایی بدیم تا نیازی به نوشتن نام کامل پکیج نداشته باشیم 142 | 143 |
144 | 145 | ```kotlin 146 | import com.antonioleiva.weatherapp.domain.model.Forecast as ModelForecast 147 | ``` 148 | 149 |
150 | 151 | یکی از بخش های جالب این کد، نحوه ی تبدیل لیست پیشبینی، از `data` به مدل `domain` است. 152 | 153 |
154 | 155 | ```kotlin 156 | return list.map { convertForecastItemToDomain(it) } 157 | ``` 158 | 159 | 160 |
161 | 162 | در یک خط، ما میتونیم بر روی یک collection حلقه ای رو تکرار کنیم و یک لیست جدید با ایتم های کانورت شده برگردونیم. کاتلین یک سری از توابع اعمالی خوبی بر روی لیست ها مهیا کرده که یک عمل را بر روی تمامی ایتم های لیست اجرا میکند و به نحو دلخواه انتقال میده! این یکی از قدرتمندترین ویژگی های کاتلین برای توسعه دهندگانی است که از java 7 استفاده میکردند. به زودی یک نگاهی به این توابع خواهیم انداخت. این مهمه که بدونیم آنها وجود دارن، زیرا که مواقع زیادی پیدا میشوند که استفاده از این توابع باعث صرفه جویی در زمان و خط های بیهوده میشود. 163 | 164 | و حالا همه چی برای نوشتن دستور مناسب است: 165 | 166 |
167 | 168 | ```kotlin 169 | class RequestForecastCommand(val zipCode: String) : 170 | Command { 171 | override fun execute(): ForecastList { 172 | val forecastRequest = ForecastRequest(zipCode) 173 | return ForecastDataMapper().convertFromDataModel( 174 | forecastRequest.execute()) 175 | } 176 | } 177 | ``` 178 | 179 | 180 | 181 |
182 | 183 | ## نمایش دیتا بر روی UI 184 | 185 | کد `MainActivity` مقداری تغییر خواهد کرد، زیرا که ما حالا دیتای واقعی برای پر کردن آداپتور خواهیم داشت. برای این باید درخواست asynchronous امون رو دوباره بنویسیم 186 | 187 |
188 | 189 | ```kotlin 190 | async() { 191 | val result = RequestForecastCommand("94043").execute() 192 | uiThread { 193 | forecastList.adapter = ForecastListAdapter(result) 194 | } 195 | } 196 | ``` 197 | 198 |
199 | 200 | آداپتور هم نیاز به مقداری تغییر دارد 201 | 202 |
203 | 204 | ```kotlin 205 | class ForecastListAdapter(val weekForecast: ForecastList) : 206 | RecyclerView.Adapter() { 207 | 208 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 209 | ViewHolder? { 210 | return ViewHolder(TextView(parent.getContext())) 211 | } 212 | 213 | override fun onBindViewHolder(holder: ViewHolder, 214 | position: Int) { 215 | with(weekForecast.dailyForecast[position]) { 216 | holder.textView.text = "$date - $description - $high/$low" 217 | } 218 | } 219 | 220 | override fun getItemCount(): Int = weekForecast.dailyForecast.size 221 | 222 | class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) 223 | } 224 | ``` 225 | 226 |
227 | 228 | * **تابع with:** یکی از توابع سودمندی که در کتابخانه استاندارد کاتلین اضافه شده است، تابع with است. به صورت خیلی ساده، این تابع یک آبجکت و یک تابع الحاقی رو به صورت پارامترهای ورودی دریافت میکند و آبجکت، آن تابع را اجرا خواهد کرد. این به این معنی است که تمام کدهایی که داخل براکت ها نوشته میشوند به صورت تابع الحاقی بر روی آن ابجکتی که به عنوان پارامتر اول دادیم، اجرا خواهند شد. 229 | 230 |
231 | 232 | 233 | -------------------------------------------------------------------------------- /src/retrieving-data-from-api/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # بدست آوردن دیتا با استفاده از API 4 | 5 | ## انجام درخواست 6 | 7 | هرچی تا الان یادگرفتیم آموزشهای مناسبی بودن که بعدا ازشون استفاده میکنیم، ولی آلان زمان مناسبیه که دیتای واقعی رو درخواست کنیم و بعدا باهاش `RecyclerView`مون رو پُر کنیم. برای دستیابی به دیتا، ما از API OpenWeatherMap و چنتا کلاس معمولی استفاده میکنیم. همینطور که گفتیم، همکاری کاتلین با جاوا واقعا قویه، پس شما میتونین از هر کتابخونه که دوست دارین استفاده کنین، به عنوان مثال برای درخواست از سرور از کتابخونه Retrofit استفاده کنیم. هرچند چون ما داریم درخواست های ساده API رو انجام میدیم نیازی نیست که لایبری سوم شخصی رو به پروژمون اضافه کنیم. 8 | 9 | علاوه بر این همینطور که بعدا میبینیم، کاتلین توابع الحاقی برامون فراهم کرده که ما میتونیم درخواست هامون رو خیلی راحت ارسال کنیم. بیاین یک کلاس ساده `Request` درست کنیم: 10 | 11 |
12 | 13 | ```kotlin 14 | class Request(val url: String) { 15 | 16 | fun run() { 17 | val forecastJsonStr = URL(url).readText() 18 | Log.d(javaClass.simpleName, forecastJsonStr) 19 | } 20 | } 21 | ``` 22 | 23 |
24 | 25 | یک URL رو به صورت ورودی دریافت میکنه و نتیجه JSON رو توی Logcat چاپ میکنه. پیاده سازی این تابع با استفاده از تابع الحاقی `readText()` خیلی ساده شده، که این تابع هم توی Kotlin Standard Library موجوده. البته برای جواب¬های بزرگ پیشنهاد نمیشه که از این تابع استفاده بشه ولی برای مورد ما به اندازه کافی خوبه. 26 | 27 | اگه این تابع رو با اونی که توی جاوا نیاز داشتیم مقایسه کنین متوجه میشین که خیلی از بارپردازشی کم شده اونم تنها با استفاده از لایبری استاندارد کاتلین. اگه میخواستیم توی جاوا همین عمل رو انجام بدیم وجود یک `HttpURLConnection` و یک `BufferedReader` و یک حلقه برای پیدا کردن نتیجه الزامی بود تازه این¬ها همه جدا از مدیریت `status` های ارتباطات و غیره و غیره است! مسلما این همین کاریه که این تابع پشت پرده انجام میده و اینو ما به راحتی در اختیار داریم. 28 | 29 | برای این که برنامه بتونه درخواست رو ارسال کنه نیاز به اجازه دسترسی به اینترنت داریم، پس وارد `AndroidManifest.xml` میشیم و خط زیر رو بهش اضافه میکنیم: 30 | 31 | 32 |
33 | 34 | ```xml 35 | 36 | ``` 37 | 38 |
39 | 40 | ## انجام درخواست خارج از نخ اصلی 41 | 42 | همینطور که میدونین درخواست HTTP اجازه نداره توی حلقه اصلی اجرا بشه،چرا که یک اکسپشن رو پرتاب میکنه! و همچنین میدونین که قفل کردن صفحه UI یک کار نادرستیه. راه حل معمول استفاده از `AsyncTask` هه ولی اگه به درستی از استفاده نشه میتونه خیلی خطرناک باشه! چون به مرور زمان به تابع `postExecute` میرسه و اون ممکنه `Activity` رو از بین ببره که باعث crash کردن اپ میشه. 43 | 44 | Anko یک DSL خیلی ساده برای کار با `asynchronous` ها تهیه کرده که میتونه نیاز های ابتدایمون رو مهیا کنه. درواقع یک تابع `async` درست کرده که میتونه کدمون رو توی نخ دیگه انجام بده! و حتی این گزینه رو برامون فراهم کرده که هرموقع خواستیم به رشته اصلی برگردیم اونم با تنها استفاده از `uiThread` . اجرای کدمون توی نخ دوم به راحتی کد زیره: 45 | 46 |
47 | 48 | ```kotlin 49 | async { 50 | Request(url).run() 51 | uiThread { longToast("Request performed") } 52 | } 53 | ``` 54 |
55 | 56 | یکی از ویژگی های جالب `uiThread` اینه که بسته به شی ای که صداش میزنه، مقداردهی میشه! اگه توی `Activity` صدا زده بشه `uiThread` اجرا نمیشه اگر `activity.isFinishing()` مقدار `true` برگردونه و درنتیجه باعث crash کردن برنامه شما نمیشه. 57 | 58 | شما حتی میتونین اجرا کننده خودتون رو بنویسین : 59 | 60 |
61 | 62 | ```kotlin 63 | val executor = Executors.newScheduledThreadPool(4) 64 | async(executor) { 65 | // Some task 66 | } 67 | ``` 68 | 69 |
70 | 71 | اگه شما بخواین با `futures` کار کنین، `async` یک `Future` جاوا برمیگردونه. حتی شما اگه بخواین یک `Future` با `result` رو برگردونین میتونین از `asyncResult` استفاده کنین! 72 | 73 | واقعا سادس نه؟ و واقعا خواناتر از `AsyncTasks` هه. فعلا من یک URL ثابت رو به عنوان درخواست میفرستم تا مطمئن شم که نتیجه¬ای که دریافت میکنم درسته و ایا من قادر هستم اینو توی `Activity` نشون بدم. راجع به نحوه pars کردن فایل های JSON و تبدیلشون به کلاس های دیتا صحبت میکنیم ولی قبل از اون لازمه که بدونیم که اصلا کلاس های دیتا چی هستن. 74 | 75 |
76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/translator-talk/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Android/8b7c60dc86a7b48c920ffb243d606f1d42a45b90/src/translator-talk/README.md -------------------------------------------------------------------------------- /src/variables-and-properties/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # مقادیر و خصیصه ها 4 | 5 | توی کاتلین همه چیز شی هه! اینجا مثل جاوا تایپ های اولیه نداریم و این خیلی خوبه، چون در اینصورت ما یک روش درست حسابی برای برخورد با تایپ های مختلف داریم و اینجوری نیست که بگیم خب الان اینه باید اینکار رو بکنیم و اگر اون بود فلان کار رو . همیشه و همیشه یک روش برخورد با تایپ ها داریم. 6 | 7 | ## تایپ های پایه ای 8 | 9 | البته که تایپ های پایه ای مثل `integers`, `float`, `characters` و یا `Boolean` هنوز وجود دارن ولی همه¬ی اینا تو کاتلین یک شی ان.نام تایپ های ابتدایی و نحوه برخورد با اونها هنوز مثل جاوایه ولی یک سری تفاوت هایی هست که باید اونهارو درنظر بگیرین: 10 | 11 | * هیچ تبدیل اتوماتی بین تایپ های شمارشی وجود نداره.به عنوان مثال شما نمیتونین یک `Int` رو به یک متغیر `Float` بدین .اگه بخواین چنین اعمالی انجام بدین باید با توابع مربوطه به صورت صریح بیان کنین: 12 | 13 |
14 | 15 | ```kotlin 16 | val i: Int = 7 17 | val d: Double = i.toDouble() 18 | ``` 19 | 20 |
21 | 22 | * کارکترها `Char` نمیتونن به صورت مستقیم به عنوان تایپ شمارشی استفاده بشن.هرچند هر موقع خواستیم میتونیم با توابع مربوطه اون کارهارو انجام بدیم. 23 | 24 |
25 | 26 | ```kotlin 27 | val c: Char = 'c' 28 | val i: Int = c.toInt() 29 | ``` 30 | 31 |
32 | 33 | * عملگرهای محاسباتی بیتی یکم متفاوتن.توی اندروید باید از “and” و یا “or” استفاده کنیم. 34 | 35 |
36 | 37 | 38 | ```java 39 | // Java 40 | int bitwiseOr = FLAG1 | FLAG2; 41 | int bitwiseAnd = FLAG1 & FLAG2; 42 | ``` 43 | 44 | ```kotlin 45 | // Kotlin 46 | val bitwiseOr = FLAG1 or FLAG2 47 | val bitwiseAnd = FLAG1 and FLAG2 48 | ``` 49 | 50 |
51 | 52 | * همینطور که میدونین توی کاتلین نیازی نیست که مشخص کنین این دقیقا چه تایپی داره، کاتلین خودش میفهمه ولی بعضی اوقات تشخیص دشوار میشه.به عنوان مثال وقتی مقدار 10 یه یک متغیر داده میشه، ایا منظور توسعه دهنده `Int` بوده یا `Double` ؟ در اینجا از یک سری حروف استفاده میشه تا کامپایلر متجه تایپ مورد نظر بشه. 53 | 54 |
55 | 56 | ```kotlin 57 | val i = 12 // An Int 58 | val iHex = 0x0f // An Int from hexadecimal literal 59 | val l = 3L // A Long 60 | val d = 3.5 // A Double 61 | val f = 3.5F // A Float 62 | ``` 63 | 64 |
65 | 66 | به یک رشته میشه به مانند یک آرایه دسترسی پیدا کرد و میشه روش حرکت کرد: 67 | 68 |
69 | 70 | ```kotlin 71 | val s = "Example" 72 | val c = s[2] // This is the Char 'a' 73 | 74 | // Iterate over String 75 | val s = "Example" 76 | for (c in s) { 77 | print(c) 78 | } 79 | ``` 80 |
81 | 82 | ## متغیر ها 83 | 84 | متغیر ها در کاتلین دوصورت دارن، یا مصون اند(`val`) یا میتونن تغییر کنن(`var`) به مانند `final` توی جاوا. ولی مصون بودن توی کاتلین یک مفهوم خیلی مهمیه. اگه یک متغیر مصون باشه به این معنیه که بعد از مقدارگیری نمیتونه مقدارش تغییر کنه. اگه شما مقدار تغییر یافته از این شی رو میخواین، باید شی جدید ازش بسازین! توی جاوا اکثر متغیرها قابل تغییر بودن، به این معنی که هر قسمت از کد که دسترسی به این متغیر داشت میتونست مقدارش رو عوض کنه. 85 | 86 | متغیر های مصون همچنین `thread-safe` اند. چون نمیتونن تغییر کنن پس هیچ کنترل دسترسی لازم نیست تعریف بشه چون هر نخ در واقع یک شی رو دراختیار میگیره که دیگری گرفته. 87 | 88 | **نکته کلید: تاجای ممکن از `val` استفاده کن.** 89 | 90 | ناقص و نیاز به تکمیل دارد 91 | 92 | ## خصیصه ها 93 | 94 | بذارین اینطور بگم، خصیصه ها مثل متغیر های **field** توی جاوا میمونن. خصیصه ها کار **field** رو انجام میدن.ولی یک تفاوت هایی با هم دارن.به عنوان مصال بیاین تفاوت های این دوتا رو مقایسه کنیم: 95 | 96 |
97 | 98 | ```java 99 | public class Person { 100 | private String name; 101 | public String getName() { 102 | return name; 103 | } 104 | public void setName(String name) { 105 | this.name = name; 106 | } 107 | } 108 | // … 109 | Person person = new Person(); 110 | person.setName("name"); 111 | String name = person.getName(); 112 | ``` 113 | 114 |
115 | 116 | و توی کاتلین ما تنها یک خصیصه نیازداریم! 117 | 118 |
119 | 120 | 121 | ```kotlin 122 | public class Person { 123 | var name: String = "" 124 | } 125 | // ... 126 | val person = Person() 127 | person.name = "name" 128 | val name = person.name 129 | ``` 130 | 131 | 132 |
133 | 134 | بدون این که شما یک خط کد بنویسین خصیصه هم `getter` رو داره و هم `setter` . البته که شما میتونین این توابع رو شخصی سازی کنین و به صورت دلخواهتون در بیارین. 135 | 136 |
137 | 138 | ```kotlin 139 | public class Person { 140 | var name: String = "" 141 | get() = field.toUpperCase() 142 | set(value) { 143 | field = "Name: $value" 144 | } 145 | } 146 | ``` 147 | 148 |
149 | 150 | اگه یک خصیصه در توابع دلخواه `getter` و `setter` خودش، نیاز به دسترسی به مقدار خودش داشت از کلیدواژه ای به نام `field` استفاده میشه و به این روش هم `backing field` میگن. 151 | 152 | همینطور که قبلا گفتیم، کاتلین دسترسی به java داره و میتونه باهاش همکاری کنه، همینطور گفتیم که توی یک فایل کاتلین وقتی میخوایم به یک متغیر `field` دسترسی داشته باشیم نیازی به استفاده از `getter` و `setter` نداریم و میتونیم مستقیم به اون `field` به عنوان یک خصیصه دسترسی داشته باشیم.ولی یادتون باشه که این روش عملکرد رو ضعیف نمیکنه و خود کامپایلر در زمان کامپایل از تابع جاوای درست استفاده میکنه! 153 | 154 |
155 | -------------------------------------------------------------------------------- /src/writing-your-first-class/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # نوشتن اولین کلاس 4 | 5 | خب ما تا الان فایل `MainActivity.kt` مون رو درست کردیم.ولی اگه یادتون باشه قرار بود یک اپ پیشبینی آب و هوا درست کنیم و باید توی صفحمون از پیشبینی آب و هوای هفته بعد گفته بشه پس نیاز به یک سری تغییرات داریم. 6 | 7 | ## ساختن layout 8 | 9 | بهترین `view` که میتونه لیست پیش بینی آب و هوا بسازه یک `RecyclerView` هه و بنابراین به یک وابستگی نیازمنده.بنابراین نیاز داریم که `build.gradle` رو تغییر بدیم: 10 | 11 | 12 |
13 | 14 | ```groovy 15 | dependencies { 16 | compile fileTree(dir: 'libs', include: ['*.jar']) 17 | compile "com.android.support:appcompat-v7:$support_version" 18 | compile "com.android.support:recyclerview-v7:$support_version" 19 | // ... 20 | } 21 | ``` 22 | 23 |
24 | 25 | و حالا بریم سر `activity_main.xml` و اونو تغییر بدیم: 26 | 27 |
28 | 29 | ```xml 30 | 33 | 37 | 38 | ``` 39 |
40 | 41 | داخل `MainActivity.kt` اون خط کدی که نوشتیم برای تست رو پاک میکنیم.همینطور که گفتیم اگه بخوایم کامپوننتی رو از توی `xml` صدا بزنیم کافیه از `id`یش استفاده کنیم.ولی فعلا به همون روش قدیمی استفاده از `findViewById` ادامه میدیم: 42 | 43 |
44 | 45 | ```kotlin 46 | val forecastList = findViewById(R.id.forecast_list) as RecyclerView 47 | forecastList.layoutManager = LinearLayoutManager(this) 48 | ``` 49 | 50 |
51 | 52 | همینطور که میبینین ما یک متغیر تعریف کردیم و به RecyclerView کستش کردیم.و همچنین به جای setter خودمون مستقیم به layoutManager دسترسی پیداکردیم.یک لیست برای این layout کافیه پس به استفاده از یک LinearLayoutManager بسنده کردیم. 53 | 54 | _**نمونه سازی:** اگه دقت کنین اینجا دیگه از کلیدواژه `new` استفاده نشد! در واقع برای ساختن یک شی دیگه نیازی به استفاده از `new` نیست تنها کافیه از نام کلاس و سازنده اش استفاده بشه._ 55 | 56 | ## آداپتور Recycler 57 | 58 | همینطور که متوجه شدین اینجا نیازمند یک اداپتور برای `RecyclerView` مون هستیم.فعلا تنها از یک `TextView` برای `RecyclerView` استفاده میکنیم. یک لیست ساده از `text` ها چیزیه که فعلا بهش نیاز داریم.لازمه که یک فایل کاتلین به نام `ForecastListAdapter.kt` باز کنیم و کدهای زیر رو داخلش بزنیم: 59 | 60 |
61 | 62 | ```kotlin 63 | class ForecastListAdapter(val items: List) : 64 | RecyclerView.Adapter() { 65 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 66 | ViewHolder { 67 | return ViewHolder(TextView(parent.context)) 68 | } 69 | override fun onBindViewHolder(holder: ViewHolder, 70 | position: Int) { 71 | holder.textView.text = items[position] 72 | } 73 | override fun getItemCount(): Int = items.size 74 | class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) 75 | } 76 | ``` 77 | 78 |
79 | 80 | برگردیم به `MainActivity`، حالا لازمه که یک لیست از رشته ها درست کنیم و بعدا به آداپتورمون بدیم: 81 | 82 |
83 | 84 | ```kotlin 85 | private val items = listOf( 86 | "Mon 6/23 - Sunny - 31/17", 87 | "Tue 6/24 - Foggy - 21/8", 88 | "Wed 6/25 - Cloudy - 22/17", 89 | "Thurs 6/26 - Rainy - 18/11", 90 | "Fri 6/27 - Foggy - 21/10", 91 | "Sat 6/28 - TRAPPED IN WEATHERSTATION - 23/18", 92 | "Sun 6/29 - Sunny - 20/7" 93 | ) 94 | override fun onCreate(savedInstanceState: Bundle?) { 95 | // ... 96 | val forecastList = findViewById(R.id.forecast_list) as RecyclerView 97 | forecastList.layoutManager = LinearLayoutManager(this) 98 | forecastList.adapter = ForecastListAdapter(items) 99 | } 100 | ``` 101 | 102 |
103 | 104 | اگر مفهومی رو از کالکشن و لیستمون متوجه نشدین نگران نباشین، بعدا راجع بهش صحبت میکنیم.فعلا فقط بدونین که یک لیست غیرقابل تغییر رو با استفاده از تابع `listOf()` میتونیم درست کنیم.اون ازمون یک آرایه از ورودی ها میگیره و برامون لیست رو درست میکنه.تابع های دیگه ای هم هستن که تقریبا همین کار رو انجام میدن ولی خب بعدا راجبشون صحبت میکنیم. 105 | 106 |
107 | 108 | 109 | 110 | 111 | --------------------------------------------------------------------------------