<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمدرضا برجیان</title>
        <link>https://virgool.io/feed/@mborjian</link>
        <description>فقط یک برنامه نویس اندروید...</description>
        <language>fa</language>
        <pubDate>2026-06-16 16:56:23</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/10334/avatar/RufUim.jpeg?height=120&amp;width=120</url>
            <title>محمدرضا برجیان</title>
            <link>https://virgool.io/@mborjian</link>
        </image>

                    <item>
                <title>پردازش زبان طبیعی با spacy</title>
                <link>https://virgool.io/@mborjian/%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D8%B4-%D8%B2%D8%A8%D8%A7%D9%86-%D8%B7%D8%A8%DB%8C%D8%B9%DB%8C-%D8%A8%D8%A7-spacy-rrrjfiqpdz6k</link>
                <description>مقدمه:گفتم برای شروع، یه مقدمه‌ای بگم در مورد اینکه چرا چنین مقاله‌ای رو منتشر می‌کنم. این مقاله حاصل یک ارائه دانشگاه هست و از اونجایی که دوست دارم اطلاعاتی که به‌دست میارم رو به اشتراک بزارم، گفتم در اینجا منتشر کنم. پس ارائه‌ای در حد آشنا شدن با این کتابخونه هست و یک مقدار آموزش یک مدل فارسی رو در آخر میگم. بخش پایانی این مقاله یا همون آموزش یک مدل، شاید بشه گفت بهترین بخش این مقاله هست. نحوه آموزش مدل فارسی در مقاله‌ای در مدیوم موجود هست اما با بررسی‌ای که کردم، نیاز بود مقداری منظم‌تر و به زبان فارسی، نوشته بشه.خب اسپیسی چیه؟ اگر در حوزه پردازش زبان طبیعی کار کرده باشیم احتمال داره در موردش اطلاعات داشته باشیم و یا شاید با کتابخونه‌ای مثل NLTK کار کرده باشیم. اسپیسی هم یه کتابخونه‌ای هست برای پردازش زبان طبیعی با زبان پایتون.اسپیسی خودش رو پردازش زبان طبیعی با قدرت صنعتی معرفی میکند. و در مورد سه ویژگی صحبت می‌کند.صرفه جویی در زمان و ساخت پروداکت واقعی(‌دیگه مشخصه داره حدودا میگه من واسه ساخت یه محصول خوبم :)‌ )اجرای سریع  همراه با مدیریت حافظه چون از cython استفاده می‌کند.کامیونیتی قوی چون از سال ۲۰۱۵ فعال هستند.( منظورم همونه که تو این مدت هر سوالی نیاز باشه پرسیده بشه، پرسیده شده و شما می‌تونید به جوابتون برسید یا می‌تونید از ساخته‌هایی که وجود داره استفاده کنید)نصب اسپیسی:از طریق بخش نصب سایت خود این کتابخانه، میتونید کانفیگ مخصوص خودتون رو پیدا کنید و نصبش کنید.کانفیگ پیش‌فرض برای نصب به صورت زیر هست.pip install -U pip setuptools wheelpip install -U spacyاین دو خط بالا برای اجرای پیش‌نیاز و خود این کتابخونه هست.python -m spacy download en_core_web_smاما یه بخش اصلی برای استفاده از این کتابخانه، استفاده از یک مدل آموزش داده شده‌ هست. برای دانلود این مدل، باید مدل مورد نظرمون رو دانلود کنیم.در توضیحات کتابخونه بهمون میگه من از خیلی از زبان‌ها از جمله فارسی پشتیبانی می‌کنم. اما در بخش مدل‌ها، مدلی برای زبان فارسی وجود نداره.حالا اگر بخواهیم از مدل زبان‌های موجود استفاده کنیم، باید بدونیم معنی دستور en_core_web_sm چی هست. دو حرف اول آن یعنی en به معنای زبان هست( در اینجا زبان انگلیسی)بخش بعدی یعنی core یعنی مدلی که تمام ویژگی های مختلف مثل ریشه‌یابی، شناسایی موجودیت‌های نامگذاری شده و... را داشته باشد. ما به جای core از dep هم می‌توانیم استفاده کنیم که شناسایی موجودیت‌های نامگذاری شده را پشتیبانی نمی‌کند.بخش سوم یعنی web به این معنی هست که مدلی می‌خواهیم که در محیط وب آموزش داده شده است. میتوانیم از news  به جای آن استفاده کنیم یعنی مدل آموزش داده شده با اخبار.در آخر سایز مدل و نوع وکتورایز هست که میتونه sm (small), md (medium), lg (large) or trf (transformer) باشه.در اسپیسی، اطلاعتمون تبدیل به یک داکیومنتی میشه با آبجکت هایی به نام توکن. یعنی ما لیستی از توکن‌هارو خواهیم داشت که این توکن ها در خود اطلاعات خیلی زیادی برامون دارند.بارگزاری مدل آموزش دیده شده:برای اینکه با این کتابخونه شروع به کار کنیم، باید مدل خودمون رو بارگزاری کنیم و داکیومنت رو به مدل بدیم. برای این کار از کد زیر استفاده می‌کنیم.import spacynlp = spacy.load(&amp;quoten_core_web_sm&amp;quot)doc = nlp(&amp;quotApple is looking at buying U.K. startup for $1 billion&amp;quot)شرح برخی از ویژگی‌‌های وابستگی های زبانی:POS(Part-of-speech tagging)میخواهیم جایگاه هر کلمه رو در جمله بدونیم.import spacynlp = spacy.load(&amp;quoten_core_web_sm&amp;quot)doc = nlp(&amp;quotApple is looking at buying U.K. startup for $1 billion&amp;quot)for token in doc:    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,    token.shape_, token.is_alpha, token.is_stop)با استفاده از کد بالا، هر توکن موجود در جمله‌ای که داشتیم رو با یک حلقه بررسی کردیم و ویژگی هایی که نیاز داشتیم رو چاپ کردیم.در متغیر توکن: text (کلمه)، lemma_(ریشه کلمه)، pos_( جایگاه کلمه از نظر معنایی)، tag_( اطلاعات دقیق تر در مورد جایگاه کلمه)، dep_(ارتباط بین توکین‌ها)،shape_( شکل کلمه حروف بزرگ، نقطه گذاری، اعداد)، alpha_( حرف هست یا خیر)، is_stop( استاپ ورد است یا خیر)برخی از برچسب‌های وابستگی رایج عبارتند از:nsubj: اسم فاعلdobj: مفعول مستقیمobj: مفعولaux: فعل کمکیprep: پیش‌نهادpobj: مفعول پیش‌نهادmod: صفتadvmod: قیدcompound: ترکیبspacy.displacy.serve(doc, style=&amp;quotdep&amp;quot)با دستور بالا می‌تونیم به صورت گرافیکی وابستگی‌های بین کلمات و جایگاهشون رو مشاهده کنیم.Morphologyمورفولوژی به تجزیه و تحلیل ساختار کلمات و شناسایی اجزای تشکیل دهنده آنها مانند ریشه، پیشوند و پسوند اشاره داره. این قابلیت به شما امکان می‌دهد تا اطلاعات زبانی عمیق‌تری را از متن استخراج کنید.import spacynlp = spacy.load(&amp;quoten_core_web_sm&amp;quot)doc = nlp(&amp;quotI was reading the paper  .&amp;quot)token = doc[0]  # &#039;I&#039;print(token)print(token.morph)  # &#039;Case=Nom|Number=Sing|Person=1|PronType=Prs&#039;همونطور که مشخص هست، من اطلاعات توکن اول که در مورد I هست رو پرینت گرفتم که به عنوان مثال، این توکن در مورد اول شخص مفرد است.Lemmatization  برای ریشه یابی کلمات، میتونیم از سه روش استفاده کنیم.بر اساس قوانین( rule-based ): که همونطوری که از اسمش مشخص هست،‌بر اساس یکیسری قانون، ریشه کلمات رو پیدا می‌کند.جستجو(lookup): که براساس چیزی شبیه دیکشنری، ریشه کلمات را پیدا می‌کند.مدل آموزش دیده(EditTreeLemmatizer): که براساس یک مدل آموزش دیده ریشه کلمات را پیدا می‌کند.با استفاده از ریپازیتوری موجود در گیتهاب، می‌تونید ریشه‌یاب های مختلف رو مشاهده کنید و توسعه بدید.Named Entity Recognitionبا استفاده از این ویژگی، میتونید موجودیت آماری موجود در متن رو تشخیص بدید. به عنوان مثال وقتی در یک جمله‌ای نام یک فرد آمده است، این کتابخانه می‌تواند مشخص کند که آن بخش، نام یک فرد است.import spacynlp = spacy.load(&amp;quoten_core_web_sm&amp;quot)doc = nlp(&amp;quotApple is looking at buying U.K. startup for $1 billion&amp;quot)for ent in doc.ents:    print(ent.text, ent.start_char, ent.end_char, ent.label_)با توجه به مثال بالا، خروجی پایین رو خواهیم داشت.Apple 0 5 ORGU.K. 27 31 GPE$1 billion 44 54 MONEYبرخی  از برچسب‌های موجودیت پیش‌فرض:PERSON: نام افراد (مانند &quot;باراک اوباما&quot;، &quot;مریم میرزاخانی&quot;)ORG: نام سازمان‌ها (مانند &quot;گوگل&quot;، &quot;دانشگاه صنعتی شریف&quot;)GPE: نام مکان‌های جغرافیایی (مانند &quot;ایران&quot;، &quot;پاریس&quot;)DATE: تاریخ (مانند &quot;14 ژانویه 2024&quot;، &quot;1399-12-29&quot;)TIME: زمان (مانند &quot;10:30 صبح&quot;، &quot;ساعت 2 بعد از ظهر&quot;)MONEY: واحدهای پولی (مانند &quot;دلار&quot;، &quot;یورو&quot;)PRODUCT: نام محصولات (مانند &quot;آیفون 14&quot;، &quot;لپ تاپ دل&quot;)EVENT: نام رویدادها (مانند &quot;جام جهانی فوتبال&quot;، &quot;جشنواره فیلم کن&quot;)NORP: نام گروه‌های مذهبی، قومی و سیاسی (مانند &quot;مسلمانان&quot;، &quot;دموکرات‌ها&quot;)آموزش مدل:شاید یک بخش اصلی در این مقاله، آموزش یک مدل ساده باشه. در این بخش میخوام یک مدل ساده به زبان فارسی رو آموزش بدیم و named entity برای خودمون درست کنیم.خب در مرحله اول نیاز هست که یک متنی داشته باشیم که تگ گذاری کنیم. این متن رو آماده می‌کنیم و وارد این سایت میشیم تا بتونیم کلمات خودمون رو تگ گذاری کنیم. وقتی متن ما لود شد، از تگ جدید می‌تونیم تگ خودمون رو بسازیم و سپس با کلیک روی یک کلمه، آن کلمه رو تگ گذاری کنیم. بعد از تگ گذاری، روی دکمه ذخیره کلیک میکنیم سپس از بخش انوتیشن، بر روی export کلیک می‌کنیم. با این کار یک فایل انوتیشن دانلود می‌شود.در مرحله بعد فایل کانفیگ زبان را از سایت اسپایسی می‌توانیم دریافت کنیم.( در این بخش، فیچرهای مورد نظر را علامت می‌زنیم و با کلیک بر روی دانلود، فایل دانلود را دریافت می‌کنیم.python -m spacy init fill-config base_config.cfg config.cfgسپس با دستور بالا، کانفیگ های باقیمانده فایل خود را تکمیل می‌کنیم.ساخت train,test مدل:import spacyfrom spacy.tokens import DocBinfrom tqdm import tqdmnlp = spacy.blank(&amp;quotfa&amp;quot)db = DocBin()import jsonf = open(&amp;quotannotations.json&amp;quot)TRAIN_DATA = json.load(f)for text, annot in tqdm(TRAIN_DATA[&amp;quotannotations&amp;quot]):    doc = nlp.make_doc(text)    ents = []    for start, end, label in annot[&amp;quotentities&amp;quot]:        span = doc.char_span(start, end, label=label, alignment_mode=&amp;quotcontract&amp;quot)        if span is None:            print(&amp;quotSkipping entity&amp;quot)        else:            ents.append(span)    doc.ents = entsdb.add(doc)db.to_disk(&amp;quot./dev.spacy&amp;quot)برای تست و ترین کردن یک مدل، نیاز به داده ای برای ترین و داده ای برای تست داریم. من برای مثال در این بخش، هر دو داده را از یک فایل استفاده کرده ام. این فایل همان فایل جیسون انوتیشنی است که در مرحله قبل دریافت کردم. پس دستور بالا را یک بار برای تست اجرا میکنم و نام داده ذخیره شده در دیسک را dev.spacy و بار دیگر نام آن را train.spacy می‌گذارم.بعد از هر بار اجرا، یک فایل با نام های گفته شده برای من ذخیره می‌شود.بعد از ساخت داده های تست و ترین،حالا میتونیم مدل خودمون رو با دستور زیر با استفاده از داده ها بسازیم.python -m spacy train config.cfg --output ./output --paths.train ./train.spacy --paths.dev ./dev.spacyبعد از اجرای دستور، مدل ما در پوشه‌ای به نام output ساخته خواهد شد و میتوانیم به صورت زیر از آن استفاده کنیم.import spacynlp_ner = spacy.load(&amp;quotoutput/model-best&amp;quot)doc = nlp_ner(&amp;quotمتن مورد نظر&amp;quot)for ent in doc.ents:    print(ent.text, ent.start_char, ent.end_char, ent.label_)در آخر:امیدوارم که به عنوان یک مقاله ابتدایی، مناسب باشه برای دوستانی که میخوان از این کتابخونه استفاده کنند.یکی از مراجعی که برای آموزش مدل ازش استفاده کردم، نوشته آقای مجید پاکدل در مدیوم به این آدرس هست.ممنونم از توجهتون.</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Sat, 01 Jun 2024 17:44:58 +0330</pubDate>
            </item>
                    <item>
                <title>تست نویسی به زبان ساده(۲) - توضیحاتی در مورد تست نویسی</title>
                <link>https://virgool.io/@mborjian/%D8%AA%D8%B3%D8%AA-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%B3%D8%A7%D8%AF%D9%87%DB%B2-%D8%AA%D9%88%D8%B6%DB%8C%D8%AD%D8%A7%D8%AA%DB%8C-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-%D8%AA%D8%B3%D8%AA-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-qkhramxoupis</link>
                <description>در مقاله قبلی (تست نویسی اندروید به زبان ساده - تست نویسی چی هست و چرا تست بنویسیم؟) در مورد اینکه تست نویسی چی هست و چرا باید تست بنویسیم صحبت کردیم و چند تا از دلایل تست نوشتن رو بررسی کردیم. حالا میخوایم بریم سراغ نکات تکمیلی تر تا آماده بشیم برای پیاده سازی...انواع تست:انواع مختلفی از تست داریم مثل:چیزی که داریم تست میکنیم آیا هدفی که برای انجام داره رو درست انجام میده؟(Functional testing)چیزی که داریم تست میکنیم آیا به سرعت و درست انجام میده؟(Performance testing)چیزی که داریم تست میکنیم آیا با accessibility services همکاری خوبی داره؟ بخشی از اندروید که خدمات ویژه ای داره مثل تاک بک که برای نابینایان هست(Accessibility testing)چیزی که داریم تست میکنیم آیا با در هر دستگاه و Api های مختلف به درستی عمل میکند؟(Compatibility testing)نمیخوام در مورد انواع مختلف تست صحبت کنم و اونهارو دسته بندی کنم اما شاید در آینده بتونیم چنین مقاله ای هم داشته باشیم. بیشتر میخوام در این مقاله در مورد تست هایی صحبت کنیم که در روند اتومیشن هستن و با کدنویسی انجام میشن.همچنین تست ها با توجه به اندازه و مقیاسی که از سیستم رو تست میکنه متفاوته:تست واحد(Unit Test): تست هایی هستند که فقط بخش کوچکی از برنامه رو وریفای میکنند، مثل وریفای یک متد.تست End-To-End یا تست های بزرگ: این تست ها بخش بزرگی از اپ رو تست میکنه، مثل تست فلو کاربر یا یک صفحه.تست Medium: این تست ها معمولا دو یا چند یونیت تست رو بررسی میکنه.محیطی که قرار هست تست هارو در اون محیط اجرا کنیم...تست های ابزاری(Instrumented tests): این تست ها روی یک دیوایس اندرویدی اجرا میشن(دیوایس خودمون یا شبیه ساز). در این تست، نسخه آزمایشی برنامه نصب میشه و دستوراتی که گفته شده اجرا خواهند شد. این نوع تست ها معمولا تست های UI هستند که برنامه رو اجرا میکنند و با رابط کاربری تعامل دارند.تست های محلی(Local Test): این تست ها روی سیستم یا سرور اجرا میشن و بهشون تست های سمت میزبان هم گفته میشه. این تست ها معمولا کوچک و سریع هستن و بخش تست را از بقیه قسمت های برنامه جدا در نظر میگیرن و اون بخش رو تست میکنند.نکته ی خیلی مهم: همه تست های واحد لوکال نیستن و همه تست های end-to-end روی دستگاه فیزیکی اجرا نمیشن.نمونه ای از کد instrumented Ui تست که باعث تعامل با رابط کاربری میشه:// When the Continue button is clicked Then the Welcome screen is displayed 
onView(withText(&amp;quotContinue&amp;quot)).perform(click())  
onView(withText(&amp;quotWelcome&amp;quot)).check(matches(isDisplayed()))خب کد بالا میگه عملیات کلیک روی ویو ای که تکست Continue رو داره انجام بشه و بعد از انجام اون چک کن که ویو ای که متن Welcome رو داره نمایش داده بشه. پس در حالت معمول برای اجرای این کد نیاز داریم که شبیه ساز اجرا بشه و عملیات بالا اجرا بشه...نمونه ای از unit test// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)در این کد میخوایم یک ویومدل رو تست کنیم که بعد از زمانی که تابع loadData() رو فراخوانی کردیم، متغیر data در ویومدل خالی نباشد.چقدر باید تست بنویسیم؟میگن تو جهان های موازی برای هر خط کد یه خط تست مینویسن:) . اما در جهان ما باید طوری تست کنیم که تست های ما بتونه یک تناسب خوبی در سرعت و کاوریج برنامه داشته باشه. یعنی هم بتونه خوب بخش های مختلف برنامه رو پوشش بده و هم سرعت مناسب داشته باشه. معمولا تست هایی که روی دستگاه های واقعی اجرا میشوند سرعت پایین تری دارند.Flaky testsاین نوع تست،بدون تغییری در کد یا تست، هم نتایج قبولی و هم ناموفق را به همراه دارد. به عبارت دیگر، تست های Flaky در هر آزمایش مجزا نتیجه یکسانی ندارند.تست پوسته پوسته(Flaky) به خودی خود خطرناک نیست، اما اعتماد به نفسی که یک توسعه دهنده می تواند به کدهای تست شده خود بدهد را کاهش می دهد.معمولا مدتی بعد از نوشتن تست، متوجه میشیم که تست FLAKY هستند. مثلا فرض کنید تستی نوشته شده است بر پایه تاریخ سیستم. این تست درصورت اشتباه نوشته شدن، هنگام اجرا در برخی از تاریخ ها میتواند پاس نشود!!!برای داشتن یک تست خوب نیاز هست از معماری های قابل تست استفاده کنیم. درصورتی که معماری برنامه قابل تست نباشد، مشکلات زیادی خواهیم داشت.در صورتی که قابل تست نباشد، کلاس‌هایی که نمی‌توانند Unit test شوند، ممکن است توسط تست‌های integration یا تست‌های UI پوشش داده شوند.به طور مثال، فرض کنید بخش های منطق برنامه در ویو نوشته شده باشد، ممکن است نیاز داشته باشیم از Ui تست برای آزمایش کد استفاده کنیم در حالی که میتونستیم این کار رو با یک unit test ساده انجام بدیم.برای یک تست خوب، اندروید چه نکاتی رو گفته که رعایت کنیم؟رویکردهای جداسازیاگر بتونیم یک بخش از کلاس ، تابع یا ماژول رو جدا کنیم و اون بخش رو مورد ازمایش قرار بدیم، تست آسان تر و پرکاربرد تر خواهد شد. این عمل به عنوان جداسازی شناخته می شود، و این مفهوم مهم ترین مفهوم برای معماری قابل آزمایش است.تکنیک های متداول جداسازی شامل موارد زیر است:برنامه رو به لایه های Domain, Presentation, Data تقسیم کنیم. یا حتی برنامه رو میتونیم به ماژول های مختلف تقسیم کنیم. برای هر فیچر یک ماژول در نظر گرفته بشه.منطق رو در موجودیت هایی که وابستگی زیادی دارند(framework dependencies) وارد نکنیم مثل فرگمنت ها و اکتیویتی ها.در کلاس های ویومدل از framework dependencies مثل context استفاده نکنیم.به عنوان مثال، از Android Contexts در ViewModels استفاده نکنید.به جای پیاده سازی های مشخص(کلاس های concrete)، از رابط ها(interface) استفاده کنید. حتی اگر از  DI framework استفاده نمی کنید، از تزریق وابستگی استفاده کنید.پوشه های مربوط به تست در اندروید:پوشه androidTest:این پوشه شامل تست هایی هست که نیاز داره در یک دستگاه واقعی اجرا بشه. مانند integration test, end-to-end tests و تست های دیگه ای که JVM نمیتونه به تنهایی انجام عملکرد رو ولیدیت کنه.پوشه test:شامل تست هایی هست که در ماشین محلی اجرا میشه مثل یونیت تست.Unit Test:چه بخش هایی رو با یونیت تست، تست میکنیم؟ کلاس های viewModel,Presenterلایه data به ویژه Repositoryبخش هایی از کد که به فریمورک اندروید وابسته نیستتست برای کلاس های کاربردی مثل کلاس های utils برنامه(کلاس های ریاضی داخل برنامه و کلاس های مربوط به string ها و...)تست Edge Cases:تست بخش هایی از برنامه با سناریو های نامعمول که تستر ها و تست های بزرگ ممکنه از دستشون بدن مثل:عملیات ریاضی با اعداد منفی، صفر و Boundary conditionsهمه ی ارور های احتمالی شبکهمشکل در تحلیل جیسون( جیسون اشتباهی که از سمت سرور میاد)و...یونیت تست رو برای چه چیزی نباید بنویسیم؟برای جایی که عملکرد یک کتابخانه هندل میشه نه عملکرد کد ما(این نکته خیلی مهمه... در آینده وقتی تست مینویسیم روی این نکته خیلی تاکید داریم)برای اکتیویتی و فرگمنت و ویو... . چون برای نوشتن یونیت در اکتیویتی نیاز منابع زیادی هست و باید کانفیگ های خاصی اعمال بشه.برای چه چیزهایی یوآی تست مینویسیم؟تست یوآی صفحه مثل کلیک کاربر، تایپ کردن و... میتونیم یک تست در هرصفحه داشته باشیم.تست های جریان کاربر(User Flow) که حرکت کاربر رو شبیه سازی میکند. این تست ها تست خوبی هستن برا چک کردن کرش های زمان اجرا(run time)test coverage:برخی از ابزار های تست آماری میدن از اینکه چه میزان کد توسط تست ها پوشش داده شده است. میتونیم از این آمار ها استفاده کنیم اما به عنوان یک استراتوژی نباید بهش نگاه کنیم. مثلا یکی از راه هایی که تست کاوریج کدهاتون رو داشته باشید این هست که میتونید روی پوشه تست لوکال کلیک راست کنید و run tests with coverage رو بزنید. بعد از اجرای تست هاتون، آمار خوبی در مورد هر پوشه یا هر کلاس بهتون ارائه میده.خیلی از موارد ترجمه شده از سایت اندروید دولوپر هست که سعی کردم یه مقداری تجربه هم بهش اضافه کنم  و بیشتر توضیح بدم که شاید مفهوم رو بتونم راحت تر منتقل کنم و کامل تر باشه...اگر نکته ای بود خیلی خوشحال میشم که کامنت بزارید و بازخورد بهم بدید... پیشاپیش ازتون ممنونم</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Sun, 17 Sep 2023 18:43:41 +0330</pubDate>
            </item>
                    <item>
                <title>تست نویسی اندروید به زبان ساده - تست نویسی چی هست و چرا تست بنویسیم؟</title>
                <link>https://virgool.io/@mborjian/%D8%AA%D8%B3%D8%AA-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%B3%D8%A7%D8%AF%D9%87-%D8%AA%D8%B3%D8%AA-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%DA%86%DB%8C-%D9%87%D8%B3%D8%AA-%D9%88-%DA%86%D8%B1%D8%A7-%D8%AA%D8%B3%D8%AA-%D8%A8%D9%86%D9%88%DB%8C%D8%B3%DB%8C%D9%85-qckb82zr8lkj</link>
                <description>گاها دیدم و شنیدم که بعد از دولوپ فیچر، تست انجام نمیشه و فیچر میره برای تست توسط مسئول تست، چرا؟ چون میگن خوب وظیفه ی ما نیست که تستش کنیم دیگه مسئول داره. یا اینکه ممکنه یه جایی از برنامه رو دست بزنیم یه جای دیگه به مشکل بخوره، و گفته شده: همه رو که نمیتونیم ما تست کنیم!خب نکته اول اینه که فیچری که از سمت ما میره سمت واحد بعدیمون نباید باگ داشته باشه :) پس اگر مطمئن نیستی و اونجا باگ پیدا شد نباید بگیم که دیگه همینه دیگه باگ واسه نرم افزاره، باید حرفه ای تر عمل کنیم و جلوی باگ رو بگیریم.همه ی اینا مقدمه ای بود که بتونم در مورد تست نویسی صحبت کنم. چرا تست مینویسیم و چطور تست بنویسیم.خب اصلا تست نویسی چیه؟ به طور خلاصه، تست نویسی یکسری کدهایی هست، اضافه بر کد های اصلی نرم افزار، که در بخش های خاص مینویسیم تا بتونیم هر بخش از کد اصلی نرم افزار رو تست کنیم. مثلا اگر یک کلاس ولیدیشن داریم و یک فانکشن ولیدیشن شماره تماس، میتونیم حالت های مختلف ورودی رو به این فانکشن بدیم و ازش انتظار خروجی متناسب با ورودی هایی که وارد کردیم داشته باشیم.حالا که به زبان ساده در مورد تست نویسی صحبت کردیم میتونیم در مورد چرایی تست نویسی هم صحبت کنیم... .- چرا تست مینویسیم؟- سناریو های مختلف رو درنظر میگیریم: با نوشتن تست های مختلف و قبل از کدنویسی (TDD)، حالت های مختلف را در نظر میگیریم و از تست نشدن یک تحلیل خاص جلوگیری میکنیم. مثلا فرض کنیم برای تابعی که قرار هست یک شماره موبایل بگیره و ولید بودن شماره موبایل رو تشخصی بده میخواهیم تست بنویسیم، چندین سناریو مختلف میتونه برای تست بشه یعنی میتونیم ورودی های مختلف به فانکشن بدیم و خروجی ای که انتظارش رو داریم رو هم مشخص کنیم.مثلا:۱- شماره تلفن با ۰ وارد شده باشد.۲- شماره تلفن با + وارد شده باشد.۳- شماره تلفن با ۰۰ وارد شده باشد.۴- شماره تلفن null وارد شده باشد.۵- شماره تلفن رشته خالی وارد شده باشد.۶- شماره تلفن کمتر ۱۱ رقم باشد.و...تابع ما با توجه به نوع نوشته شدنش میتونه به هر کدام از سناریو ها واکنش مناسب نشان بده. و چون میخواهیم تست های مختلفی رو بنویسیم، به طور کامل داریم به تحلیل کدمون میپردازیم.- ترس از تغییر کد از بین میرود. (کد نویس تمیز): تا داره کار میکنه تغییرش نده! این جمله رو احتمالا خیلی شنیدیم... . اما وقتی در شرکتی مشغول به کار هستیم، معمولا قراردادی که داریم صرف دولوپ نیست و نگهداری کد هم جزو کارهای ما محسوب میشه. ما مسئول این هستیم که کد رو به روز نگهداریم و هر زمان که وارد کد میشیم، بهبود بدیم. اما ترس این رو داریم وقتی کد رو تغییر میدیم، بخشی که تغییر داشته به مشکل بخوره و از اون بدتر یه جای دیگه به مشکل بخوره. اما اینها به خودی خود ترس نداره. این ترس زمانی اتفاق میفته که باگی که اتفاق افتاده رو در جریان نیستیم و برنامه زمانی به مشکل میخوره که منتشر شده و دست کاربر هست. خب چکار کنیم که کد رو بدون ترس تغییر بدیم؟ تست بنویسیم! با تست نوشتن، خیلی راحت میتونیم کدهامون رو تغییر بدیم و اگر قسمتی از برنامه دچار مشکل بشه، قبل از اینکه به دست کاربر برسه، خودمون فیکسش کنیم.- خواندن و آنبرد شدن کد راحت تر خواهد شد.وقتی تست کد هارو میخونیم خیلی راحت تر میتونیم کد رو درک کنیم.مثلا خیلی راحت میتونیم ماهیت یک کلاس رو به دست بیاریم و کار هر یک از فانکشن های اون کلاس رو درک کنیم. البته این مرحله یک مقداری هم نیاز به مهارت دولوپر داره تا نام گذاری های مناسبی داشته باشه و به روند آنبرد شدن دولوپر بعدی روی کد کمک کنه.- با کمک اتومیشن ها، تغییراتی که موجب باگ میشه، از بین میره.میتونیم اجرای تست های برنامه رو به فرایند دولوپمون وابسته کنیم تا در زمانی که میخوایم نسخه ای رو منتشر کنیم، تست های برنامه اجرا بشن و در صورتی که اجرای این تست ها به مشکل خورد، از فرایند انتشار جلوگیری کنه. اینطوری اگر تغییراتمون باعث مشکلاتی در قسمت دیگه یا همون قسمت شده باشه رو زودتر متوجه خواهیم شد.- کدمون تمیز میشه :) ( همین یه دلیل بسه) وقتی تست مینویسیم، به طور ناخوداگاه مجبوریم یکسری قوانین رو رعایت کنیم. مثلا برای ماک کردن(اگر در موردش اطلاعی نداری بعدا مفصل در موردش صحبت میکنیم ;)‌ ) نیاز داریم تا تزریق وابستگی رو رعایت کرده باشیم. یا وقتی روی تست نویسیمون تمرکز میکنیم، توابعی مینویسیم که یک مسئولیت دارند و... .نتیجه گیریسعی کردم دلایلی رو مطرح کنم که از نظر تجربی بیشتر باهاش آشنا باشیم... . قطعا دلایل بسیار زیادی برای تست نویسی وجود داره، مثلا با نوشتن تست میتونیم کدمون رو روی Api های مختلف تست کنیم و از مشکلات رو گوشی های مختلف جلوگیری کنیم و... .اینها همگی مقدمه ای بود برای اینکه خیلی زود مقاله دوم رو داشته باشیم در مورد نحوه کد نویسی و اطلاعاتی در مورد پیاده سازی تست نویسی در اندروید.امیدوارم که تونسته باشم منظورم رو کامل برسونم و مفید باشه. از نظراتتون خیلی استقبال میکنم، ممنون از اینکه تا اینجا اومدید ...</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Wed, 23 Aug 2023 00:41:09 +0330</pubDate>
            </item>
                    <item>
                <title>دلیلی که کار میکنیم...</title>
                <link>https://virgool.io/@mborjian/%D8%AF%D9%84%DB%8C%D9%84%DB%8C-%DA%A9%D9%87-%DA%A9%D8%A7%D8%B1-%D9%85%DB%8C%DA%A9%D9%86%DB%8C%D9%85-ql9fnjhvrn3p</link>
                <description>افراد حاضرند روزانه ۸ ساعت برای حقوق ماهیانه، ۱۰ ساعت برای یک رئیس خوب و ۲۴ ساعت‌ برای یک دلیل خوب کار کنند!! جان سی مکسولواقعا why؟؟؟؟؟قصد ندارم توی کارهایی که تخصص ندارم دخالت کنم. فقط میخوام یکمی از تجربه هام در همین مدت کوتاهی که مشغول کار هستم بگم. و اینکه نوع نگاهم، از سمت شرکت ها و کارفرمایان و مدیران هست هرچند که خودم  نه کارفرما هستم و نه مدیر! :)خیلی موقع ها توی شرکت ها دیدم که کلا همه شدن شبیه ربات. یک سیستم مدیریت پروژه وجود داره(گاها این هم وجود نداره و به امید خدا پیش میبرن :) ). هرکسی میاد و یکمی تسک ازش برمیداره، انجام میده و میره.تسک ها تموم میشن و فیچر دیپلوی میشه. باگ های بعدش رو فیکس میکنند و تمام. بریم برای فیچر بعدی.خوب این فیچر چی شد؟ اصلا برای چی این رو درست کردیم؟ راه دیگه ای وجود نداشت جز این فیچر؟همیشه برام سوال بود که این که همه تسک هارو بردارند و کار به این که چرا این تسک رو انجام میدن نداشته باشن، یه جاییش مشکل داره. هرچند با بعضی از  مدیرها که صحبت کردم خیلی موافق حرف من نبودن و میگفتن که نه اتفاقا برنامه نویس ها چون اکثرا افراد درونگرایی هستند،کم صحبت میکنند و خیلی نمیخوان در مورد پروداکت یا کارهایی که میکنند صحبت کنند.یه روزی که داشتیم در مورد کسب و کارمون با آقای حجازی عزیز صحبت میکردیم، داشت از این میگفت که من بعد از این که مشکل ولید شد، اون رو در تیم فنی مطرح میکنم و راه حل رو تیم فنی میده! (البته این فقط یک جمله بود از مدتی که با هم صحبت کردیم). حس کردم خودشه، دقیقا همون چیزیه که من دنبالش بودم. چیزی که همه ی تیم رو جمع میکنه که برای یک هدف مشترک درگیر باشند. البته این موضوع سطح بالاتری هم داره. اینکه اومدیم داخل شرکت دور هم که چکار کنیم؟ بعد جواب این سوال رو که دادیم میتونیم بیایم یه لول پایین تر، مثلا داخل این تیم قرار هست چکار کنیم، چرا دور هم جمع شدیم. این میگذره تا میرسه به این که چرا قراره یه فیچری رو دور هم دولوپ کنیم؟چرایی سازمان باعث میشه افرادی رو جذب کنه که قرار هست برای یک هدف مشترک تلاش کنند. هدف بزرگی که باعث تاسیس سازمان شده. این هدف به بخش های کوچک تری تقسیم میشه تا میشه تسک.(قطعا برداشتی از کتاب با چرا شروع کنید رو دارم:)‌ ) خب در این راه چه مشکلاتی ممکن هست داشته باشیم ؟ از مشکلات این راه، سه موردی که به نظر خودم مهم تر هست رو مینویسم.۱- ممکنه شرکت ها چراییشون رو روشن و مشخص به کارمند ها ارائه نکنند. مثلا فقط برای مدیران سازمان مشخص هست و بقیه افراد از همون روال تسک برداشتن از مدیریت پروژه پیروی میکنند و بعد از حدود ۸ ساعت کار هم سیستمشون رو خاموش میکنند و میرن استراحت. یعنی بالاترین سطح چرایی، به خوبی ارائه نشده و به همین ترتیب سطح های پایین تر تیم ها و فیچر ها هم بدون چرایی خاصی برای افراد تیم هستند.۲- یکی از مشکلات شاید این هست که بعضی افراد ممکنه دنبال اهداف نباشند و دوست داشته باشند مثل مثالی که زدم، صرفا تسک هارو بدون توجه به چرایی تسک، انجام بدن(البته هر شخصی یک چرایی خاصی برای خودش داره و ممکنه در اصل چرایی این شخص با شرکت یکی نباشه!). این متن هنوز برای خودم ولید نشده اما ممکنه جزو دلایل باشه. البته اگر هم این دلیل ولید باشه، زمان جذب، منابع انسانی باید افرادی رو جذب کنه که با چرایی اول سازمان هم خوانی داشته باشند.۳- مشکل بعدی اینه که هدف واقعی نیست. وقتی یه چرایی ای رو برای یک شرکت در نظر میگیریم، همه ی تلاشمون و اهدافمون روی همون چرایی باید باشه. اگر در جهت مخالفش حرکت میکنیم، اون چرایی حرفی بیش نیست و نباید هم از افراد سازمان توقعی داشته باشیم. تاثیر بدی هم که میزاره، اینه که افرادی هم که انگیزه دارند و در جهت اون چرایی تلاش میکنند رو بی انگیزه میکنیم!.این موضوع برام مجدد قوت گرفت چون این مدت در روند مصاحبه ها هستم. داشتم به این فکر میکردم که تو این مدتی که کار کردم چه زمان هایی بیشتر در محیط کار حس خوب داشتم.دقیقا همون موقع هایی بود که چرایی رو درک میکردم، چرایی با اهداف خودم یکی بود، کل شرکت به طور واقعی در راستای اهدافش فعالیت میکرد و در مورد اینکه چکار کنیم که برسیم به آن چه که میخوایم صحبت میکردیم.خلاصه:اگر برای سازمانمون یک هدف کامل داشته باشیم، واقعی باشه و در جهتش تلاش کنیم، افرادی رو جذب کنیم که چرایی مشترک داشته باشیم باعث میشه که تیمی باشیم که ۲۴ ساعت برای یک دلیل خوب کار کنیم.پ.ن:دوست دارم نظراتتون رو بدونم و درموردش صحبت کنیم.پ.ن ۲: ممنونم از آقای حجازی عزیز که خیلی چیزا بهمون یاد دادند.صفحه آقای حجازی در لینکدین: https://www.linkedin.com/in/michael-hejazi/</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Thu, 11 May 2023 16:14:12 +0330</pubDate>
            </item>
                    <item>
                <title>رهبر خوب کیه؟</title>
                <link>https://virgool.io/@mborjian/good-leader-yps38uewdhod</link>
                <description>تفاوت رهبر و مدیرچندسالی هست که برنامه نویسی میکنم.کلا به فریلنسری علاقه خاصی نداشتم. همیشه دوست داشتم عضو یه تیمی باشم و با هم برای یک هدف بجنگیم.تو این مدت یکسری نکته در مورد رهبری فهمیدم. در مورد اینکه یک رهبر خوب کیه و باید چه خصوصیاتی داشته باشه.اسم مدیر نیاوردم به همون دلایل فرق مدیر و رهبر و... .  چون میخوام در مورد رهبر و ویژگی های رهبری صحبت بگم.یادمه یه زمانی یه جایی کار میکردم. یه ایده ای برای اپلیکیشنمون داشتم. رفتم به مدیرمون گفتم و خیلی خوشحال شد. قرار شد با مدیرعامل درجریان بزاره و نتیجه رو به من بگه. جلسشون شروع شد و بعد از ۱ ساعت با من تماس گرفتند و از من خواستند که در جلسه شرکت کنم. نکته جالبی بود، مدیرم بدون اینکه به این فکر کنه شاید با گفتن ایده بتونه حتی جایگاهشو بهتر کنه، اون رو کاملا از زبان من بیان کرده بود و با صحبت هاش باعث شد که راه برای من باز بشه برای صحبت کردن. همیشه این مورد تو ذهنم بود و همه جا سعی کردم کار های افراد دیگه رو با نام خودشون اطلاع رسانی کنم، به خاطر اون حس خوبی که از این جریان داشتم.حس رهبری حسیه که به بقیه منتقل میکنیم. حسی که آدم دوست داره برای رسیدن به هدفش تلاش کنه.بنظرم رهبر خوب باید یکسری رفتار هارو انجام بده و یکسری خصوصیت خوب داشته باشه.رهبر خوب از نظر من کیه؟۱- رهبر خوب مثل همه ی این مقاله هایی که نوشته شده، خودش توی خط مقدم هست و داره تلاش میکنه که به هدف برسیم.۲- رهبر خوب هوای تک تک اعضای گروهش رو داره. این نکته خیلی خیلی مهمه. گاها دیده میشه بعضی ها کار های خیلی خوبی انجام میدن اما چون همیشه یه گوشه نشستن و کارهاشونو به نمایش نمیزارن، دیده نمیشن و بلعکسشم یسری با شوآف کردن سعی در بزرگنمایی کار ها دارن. حالا اگر رهبر خوبی وجود نداشته باشه باعث میشه بعضی افراد با کار های کوچک بزرگ شوند و بعضی دیگر با کارهای بزرگ کوچک.۳- رهبر خوب جلوی رشد افراد گروهشو نمیگیره. گاها دیدم که بعضی ها چون فردی با دانش درگروه وجود داره، جلوی رشدش رو با کار های کاذب میگیرن یا حتی از گروه خارجش میکنند اما رهبر خوب کمک میکنه همه افراد رشد کنند حتی بیشتر از خودش.۴- رهبر خوب محدودیت هارو از بین میبره. یه موقع هایی یکسری محدودیت ها باعث مشکل میشه. شاید باعث بشه تیمت رشد نکنه، شاید باعث بشه تیمت دیده نشه یا حتی مشکلات بدتر. رهبر خوب برای رفع محدودیت ها میجنگه.۵- رهبر خوب هوای تیمش رو در مقابل بالا دستی ها داره. یه موقع فشار هایی از بالا به تیم وارد میشه که باید از سمت رهبر مدیریت بشه. باید از فشار های اضافی که تیم رو از پا درمیاره جلوگیری بشه تا درازمدت تیم تواناییاش کمتر نشه.۶- رهبر خوب واقع گراست. وقتی رویا پرداز باشی ممکن اشتباهات زیادی داشته باشی و درخواست هایی رو قبول کنی که توانایی انجامش رو نداشته باشی. ممکنه استیمیت هایی بدی که فشار زیادی رو به تیم وارد کنی و در آخر هم سر استیمیت نتونی تحویل بدی.۷- رهبر خوب تنهایی رشد نمیکنه.گاها دیده میشه که با برون سپاری کار های خرد به بقیه، زمان برای خودشون میخرن تا بتونن بیشتر رشد کنند و اصطلاحا یک سرو گردن از بقیه بالاتر باشن.۸- رهبر خوب اشتباهات خودش رو به اعضای تیم میگه و عذرخواهی میکنه. یک رهبر معصوم نیست و ممکن هست اشتباهاتی داشته باشه، هرچند باید سعی کنه این اشتباهات کم باشه، اما با گفتن اشتباهات و درس گرفتن از آن راه رو باز میکنه که اگر کسی اشتباهی داشت زودتر از اینکه فاجعه ای رخ بده، اعلام کنه.۹- رهبر خوب انتقاد پذیر هست. پذیرش انتقاد معمولا سخته وشنیدنش هم آزار دهندس. اما اگر انتقاد هارو بگیریم و تا جای ممکن سعی کنیم درموردشون فکر کنیم باعث میشه حس خوب رهبری رو بین اعضا انتقال بدیم.۱۰- رهبر خوب برای پیدا کردن سر منشا مشکلات، اول از خودش شروع میکنه. خیلی وقتا وقتی مشکلی پیش میاد، همه میگن مشکل از شخص دیگه ای هست. اما یه رهبر خوب باید ببینه خودش چه اشتباهی داشته که این مشکل به وجود اومده.این ها ۱۰ ویژگی ای بود که من در این مدت در مورد مدیریت و رهبری گروه ها و تیم ها متوجه شدم. آسیب هایی که نداشتن هرکدوم از این ویژگی ها به تیم و خود شخص وارد شده است رو دیدم. مطمئنا ویژگی های بیشتری وجود دارد اما نکاتی که من بهشون برخورد کردم در این ده مورد خلاصه میشه.نظراتتون رو به اشتراک بگذارید تا باعث بشه در این مورد با هم رشد کنیم...</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Mon, 21 Mar 2022 13:53:04 +0330</pubDate>
            </item>
                    <item>
                <title>استفاده از OSM و Map.ir</title>
                <link>https://virgool.io/@mborjian/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-osm-%D9%88-mapir-shxbdjkv4lsh</link>
                <description>OSM/Map.irسلام دوستان عزیزچند سال پیش وقتی داشتم یک اپ مپ بیس مینوشتم، نیاز داشتم که از Osm یا open street map استفاده کنم. خوب همونطور که میدونید یا شاید هم اطلاع ندارید، برای استفاده از از تایل های osm(تایل ها منظورم همون کاشی هایی هست که کنار هم قرار میگیرن و نقشه رو کامل میکنند) محدودیت وجود داره و شما باید از تایل های خودتون استفاده کنید. برای اون زمان من باید از تایل های ارائه شده در سایت map.ir و کتابخونه osm استفاده میکردم و این تایل هارو با osm  مچ میکردم. یادمه که دیتای زیادی وجود نداشت دراین باره.چندین بار بود که میخواستم کلاسی که برای این کار ساخته بودم رو با دوستان به اشتراک بگذارم، اما متاسفانه فرصت کافی نبود. اما بالاخره میخوام این کار رو انجام بدم.برای این کار یک ریپازیتوری در گیت هاب به نام mapir ساختم. که برای مشاهدش میتونید اینجا کلیک کنید.در این پروژه از یک کلاس  به نام MapIrTileProvider استفاده کردم. در این کلاس یسری دیتای پیش فرض گذاشتم که میتونید تغییرش بدید. اما مهمترین نکته ای که وجود داره این هست که در متغیر apiKey باید توکن مربوط به خودتون رو که از سایت  Map.ir دریافت میکنید وارد کنید.این کلاس رو باید به mapView.setTileSource بدید.صرفا از کلاس استفاده کردم و اون رو به زبان کاتلین تبدیل کردم و خیلی زمان برای تغییرات بیشتر صرف نکردم و بیشتر هدفم این بود اگر دوستی به مشکل من خورده بود، بتونه سریع تر مشکلش رو حل کنه. دوستان میتونند خودشون تغییرات رو اعمال کنند.</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Tue, 05 Oct 2021 21:36:33 +0330</pubDate>
            </item>
                    <item>
                <title>کتابخونه Lottie for Android</title>
                <link>https://virgool.io/CodeLovers/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D9%88%D9%86%D9%87-lottie-for-android-zo7ug6aq7fjw</link>
                <description>LottieAnimationسلام به همه ی دوستان عزیز امروز میخوام اولین پست خودم رو در قالب یک آموزش تجربی ارائه بدم... شاید با یک سرچ ساده بتونید خیلی آموزش به زبان فارسی یا انگلیسی از این کتابخونه پیدا کنید، اما من میخوام کار با این کتابخونه رو به صورت تجربی آموزش بدم، شاید بعضی از دوستان بهش نیاز داشته باشن. اول از همه بریم سراغ معرفی این کتابخونه:Lottie is an iOS, Android, and React Native library that renders After Effects animations in real time, allowing apps to use animations as easily as they use static images.این معرفی، از زبان خود شرکت سازنده هست.این کتابخانه برای نمایش انیمیشن داخل برنامه های موبایل است مانند نمایش عکس های استاتیک. برای نمایش انیمیشن ها از فایل جیسون استفاده میکنه که با استفاده از یک افزونه در افترافکت به نام Bodymovin میتونید فایل جیسون مربوط به انیمیشنتون رو بسازید.این کتابخونه میتونه فایل جیسون خودش رو از ادرس اینترنتی هم لود کنه که خودش میتونه خیلی کمک کنه مخصوصا در مبحث A/B Testing. همچنین از مبحث کش هم استفاده میکنه.خلاصه کلی ویژگی های خوب داره برای اینکه یخورده نرم افزار رو کاربرپسند تر کنیم.برای آشنایی بیشتر با این کتابخونه میتونید از آدرس های زیر استفاده کنید:۱- introducing-lottie۲- lottie-androidخب بعد از این مقدمه میتونیم بریم سراغ کار با این کتابخونه:کار با این کتابخونه در حالت عادی کار سختی نیست. برای نمایش انیمیشنتون میتونید از کد های xml  یا کد جاوا استفاده کنید.فایل جیسون انیمیشنتون میتونه داخل پوشه raw، پوشه assets یا به صورت url باشه.برای ادرس دهی میتونید مانند زیر عمل کنید&lt;com.airbnb.lottie.LottieAnimationView
    android:id=&amp;quot@+id/lottieAnimation&amp;quot
    android:layout_width=&amp;quotmatch_parent&amp;quot
    android:layout_height=&amp;quotmatch_parent&amp;quot
    app:lottie_fileName=&amp;quotanimations/animation.json&amp;quot
    app:lottie_autoPlay=&amp;quottrue&amp;quot/&gt;در اینجا برای نمایش فایل از پوشه assets ، از app:lottie_fileName استفاده کردیم. فایل انیمشن ما در پوشه animation  و با نام  animation.json موجود می باشد.برای خواندن فایل به صورت آنلاین میتونید از app:lottie_url استفاده کنید و آدرس یوارال مورد نظرتون رو بدید.اما گاهی پیش میاد که میخواهید مثلا چند انیمیشن رو پشت سر هم نمایش بدید. باید به این نکته توجه کنید که این فایل برای لود شدن نیاز به زمان دارن و اگر بخواهید پشت سر هم خیلی سریع نمایش بدید فایل ها ممکنه با یک مکس نمایش داده بشن که خوب میتونه جذاب نباشه.برای جلوگیری از این کار شما میتونید از LottieComposition استفاده کنید.میشه گفت با این کار فایل های جیسون رو parse میکنید و هر زمانی که خواستید میتونید این اطلاعات رو به ویو بدید تا انیمیشن رو نمایش بده. این کار باعث میشه سرعت بره بالا و از دیلی جلوگیری کنه.برای نمونه به این کد دقت کنید.private fun getComposition():ArrayList&lt;LottieComposition&gt; {
    val composition :ArrayList&lt;LottieComposition&gt; = ArrayList()
    for (re in list) {
        val result = LottieCompositionFactory.fromAssetSync(this, re)
        composition.add(result.value!!)
    }
    return composition
}با استفاده از کد بالا آرایه ای درست کردیم از نوع LottieComposition و لیستی داریم که نام فایلها در assets رو داره. هر فایل رو به LottieCompostion تبدیل میکنیم و به آرایه اضافه میکنیم تا هر زمان که خواستیم بتونیم ازشون استفاده کنیم. و حتی میتونیم بگیم که مثلا تا زمانی که ایتم ها در حال تبدیل شدن هستند پروگرس بار نمایش داده بشه. مثلا داخل ویوپیجر...و اما در آخرگاهی نیاز دارید که از یک listener برای دریافت زمان اتمام کار انیمیشن استفاده کنید.مثلا بعد از اتمام انیمیشن یک کار خاصی انجام بشه. برای این کار از کد زیر استفاده میکنیمlottieAnimation.addAnimatorListener(object : AnimatorListener {
    override fun (animation: Animator) {}
    override fun (animation: Animator) {

        //animation repeat
    }

    override fun (animation: Animator) {}
    override fun onAnimationRepeat(animation: Animator) {}
})اما یادمون باشه باید در در onDestroy صفحمون انیمیشن رو کنسل کنیم تا برنامه گاها کرش نکنهoverride fun onDestroy() {
    lottieAnimation.cancelAnimation()
    super.onDestroy()
}یک ریپازیتوری به گیتهاب اضافه کردم برای کد های بالا که همین هارو داخلش نوشتم همراه با ویو پیجری که شامل ۳ انیمیشن هست و قرار هست پشت سر هم نمایش بدیم. میتونید از این لینک ریپازیتوری رو مشاهده کنید.یک نکته خیلی مهم در مورد جیسون فایل ها اینه که اگر خودتون میخواهید درست کنید. کاری کنید که حجم این فایل ها خیلی بالا نباشه، چون ممکنه حافظه کم بیاره و OOM دریافت کنید و کیفش رو ببرید :)چندتا نکته:۱- برای دانلود فایل های انیمیشن میتونید از سایت خود کتابخونه استفاده کنید.(https://lottiefiles.com)۲- برای داکیومنت خوب میتونید از این لینک استفاده کنید.۳- برای ادیت فایل جیسونتون میتونید از این لینک استفاده کنید.۴- در مورد ویژگی های دیگه یا بقیه امکانات در این پست وقت نشد چیزی اضافه کنم. اگر دوستان نیاز دیدند میتونم دومین قسمت پست رو هم درست کنم.در آخر:خیلی خوشحال میشم که با پیشنهاد و انتقاد باعث رشد همدیگه بشیم...</description>
                <category>محمدرضا برجیان</category>
                <author>محمدرضا برجیان</author>
                <pubDate>Thu, 11 Mar 2021 15:38:29 +0330</pubDate>
            </item>
            </channel>
</rss>