<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مجتبی حدادی</title>
        <link>https://virgool.io/feed/@mojtabaha</link>
        <description>برنامه نویس اندروید - اسنپ</description>
        <language>fa</language>
        <pubDate>2026-06-16 14:59:38</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/29341/avatar/vQ2jfr.png?height=120&amp;width=120</url>
            <title>مجتبی حدادی</title>
            <link>https://virgool.io/@mojtabaha</link>
        </image>

                    <item>
                <title>Sequence ها در کاتلین</title>
                <link>https://virgool.io/@mojtabaha/sequence-%D9%87%D8%A7-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%AA%D9%84%DB%8C%D9%86-mdnmx2dob4gh</link>
                <description>توی این نوشته سعی میکنم در مورد sequence ها در کاتلین صحبت کنم که به نظرم میرسه یکی از بخش های جالبی هست که کمتر مورد توجه قرار گرفته. سعی میکنم با یک مثال ساده جلو برمفرض کنید لیست اعداد 1 تا 9 رو به این شکل داریم.و حالا میخواهیم به این شکل عمل کنیم که : اقلام لیست رو ضرب در 2 کنیم.از نتیجه یکی کم کنیم.سه قلم اول رو برگردونیم.یعنی کدی که میزنیم به این شکل خواهد شد.نتیجه هم مشخصه . یک لیست به شکل زیر.ولی بیاید با هم فکر کنیم برای این که به این لیست برسیم. چقدر هزینه دادیم.اول کار یک لیست از 1 تا 9 داشتیم .  بعدش با فانکشن map ای که نوشته شد به یک لیست 9 تایی دیگه رسیدیم که همه ی اقلامش ضرب در 2 شدن. ( ساخته شدن یک لیست جدید و انجام عمل ضرب روی آیتم های قبلی و ریختن توی لیست جدید )بعد دوباره روی این لیست جدید هم یک عملیات دیگه انجام دادیم که همه ی قلم ها یکی ازشون کم شد و به یک لیست دیگه رسیدیم . (ساخته شدن لیست جدید دوم و انجام عمل  تفریق روی آیتم های قبلی و ریختن توی لیست جدید دوم ) و در انتها هم انتخاب سه تا آیتم ابتدای این لیست. (ساخته شدن یک لیست جدید سوم و اضافه شدن سه تا آیتم)عکس زیر رو ببینید.همونطور که مشخصه داریم هزینه ی زیاد و غیر ضروری ای رو پرداخت میکنیم.برای مثال  2 * 8  یکی از اون عملیات هایی هست که هیچ نیازی بهش نداشتیم و توی نتیجه نهایی هم تاثیری نداشته.استفاده از sequencesحالا فرض کنید به جای روش بالا به این شکل عمل کنیم که برای 3 تا قلم اول ( (take(3 ) ، قلم اول رو انتخاب کنیم ، ضربدر 2 ، منهای یک . مجدد برای قلم دوم و به همین ترتیب ... رفتاری شبیه به شکل زیر یعنی به جای اینکه مراحل رو افقی بریم ؛ عمودی بریم.نتیجه این میشه که با تعداد محاسبات کمتر به نتیجه ی یکسانی میرسیم.اما حالا چطور میشه چنین کاری رو انجام داد ؟توی کاتلین یه extension function هست که یک لیست رو میگیره و اون رو به sequence تبدیل میکنه. کد زیر رو ببینید.این کد ، 2تا تفاوت با کد قبلی داره. متدهای ()asSequence و ()toList .که این دو خط باعث ورود و خروج ما از دنیای تفکر sequence ای میشن!البته اون متد های map و take هم که اون وسط وجود دارن ظاهرا تفاوتی با کد قبلی ندارن، ولی در واقع یک تفاوت اساسی دارن ، قبلی ها روی لیست ها یا دقیق تر بگم Iterable ها کار میکنن ولی این یکی ها ، روی Sequence ها . تعریف این دو تا متد رو ببینید. &quot; /&gt;Iterable

&quot; /&gt;Sequence

به طور کلی 2 دسته اپراتور برای sequence وجود داره.اپراتور های میانی (Intermediate)  یا به قولی &quot;در میان واقع شونده&quot; مثل mapاپراتور های پایانی (terminal) یا &quot;پایانه&quot;. مثل toListمیشه گفت رفتاری که که sequence ها دارن یک رفتار lazy طور هست. به این معنی که شما اگر توی کد قبلی از map استفاده میکردین، در لحظه، کد اجرا میشد و خروجیش مشخص بود ولی توی sequence ها همه ی اپراتور های میانی توی یک لیست که operation ها رو نگه میداره اضافه میشن و تا زمانی که به یک اپراتور پایانی مثل ()toList برسیم اجرا نمیشن.شروع sequence هاهمیشه لازم نیست که یک لیست داشته باشیم و با متد ()asSequence بقیه ی عملیات هامون رو شروع کنیم. یعضی وقت ها میشه از همون اول کد sequence ای زد . این جا رو ببینید. متد ()generateSequence با ورودی 1 ، از عدد 1 شروع میشه و برای محاسبه ی عدد بعدی اون رو +2 میکنه.حالا ما میخواهیم که تا 5 بار این کار انجام بشه و در آخر یک لیست برگردونده میشه.یک نکته ی جالب این کد داره ، به هر تعدادی که کاربر مشخص میکنه محاسبات انجام میشه. یعنی میشه گفت تا بی نهایت میتونه مقادیر رو حساب کنه .این هایی که دیدیم تازه چندتا از متدهای ساده ای بود که توی پکیج sequence ها وجود داره. یه نگاه به لینک زیر بندازید.https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/#functionsاستفاده از sequence ها یعنی پرفورمنس بالاتر ؟قطعا خیر! فرض کنید به جای 3 تا آیتم اول لیست همه ی آیتم ها رو میخواستیم. take(9)یعنی تعداد محاسباتی که لازم بود تا به جواب آخر برسیم تقریبا به اندازه ی همون حالت قبلی میشد به اضافه این که لازم بود توی حافظه آبجکت هایی برای نگهداری مراحل نگهداری بشه که این ها یعنی عملا به پرفورمنس بالاتری نمیرسیدیم.جمع بندیمیشه گفت با در نظر گرفتن بعضی از شرایط ، sequence ممکنه بهتر از collection عمل بکنه، فقط همین! البته اگر تعداد اقلام کم باشه خیلی تفاوتی بین استفاده از collection ها (روش اول) و sequence ها نیست. (مثل مثال ما که روی 9 تا آیتم بود).خیلی خوشحال میشم در صورتی که این نوشته رو دوست داشتید ❤️ کنید یا نظرتون را از طریق کامنت برام بنویسید.</description>
                <category>مجتبی حدادی</category>
                <author>مجتبی حدادی</author>
                <pubDate>Thu, 30 Jul 2020 14:36:59 +0430</pubDate>
            </item>
                    <item>
                <title>مفهموم Delegation و پیاده سازی در کاتلین</title>
                <link>https://virgool.io/@mojtabaha/%D9%85%D9%81%D9%87%D9%85%D9%88%D9%85-delegation-%D9%88-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%AA%D9%84%DB%8C%D9%86-icyadzrpzbqg</link>
                <description>در این نوشته سعی میکنم مفهوم Delegation رو توضیح بدم. بعد از اون بگم کاتلین چطور پیاده سازیش کرده. مفهومی که شاید برای کسی که اسمش رو میشنوه یکم سخت به نظر برسه ولی چند دقیقه بعد میبینیم که این طور نیست.نمایندگی یا Delegationفرض کنید ما میخواهیم یک کلاس B داشته باشیم که عملکرد های یک کلاس دیگه مثل A رو داشته باشه.2 روش برای انجام این کار وجود داره.1. روش اول : استفاده از Inheritance یا وراثت. با این کار یک رابطه ی غیر قابل تغییر بین کلاس های A و B ایجاد میشه.2. روش دوم:  استفاده از Delegation یا واگذاری مسئولیت : یک شی از نوع A (یا کلاس های فرزندش) رو به شی ای از کلاس B پاس میدیم. به این ترتیب کل کارهایی رو که A میتونسته انجام بده B هم میتونه انجام بده.پس میشه Delegation رو اینجوری تعریف کرد: واگذار کردن کارها از یک Object به Object دیگه.به صورت کلی میشه Delegation رو به 2 روش پیاده سازی کرد. پیاده سازی با زبان های شی گراپیاده سازی در سطح زبان (مثل Kotlin)پیاده سازی با زبان های شی گراهمون طوری که از نامش هم مشخص هست وابسته به زبان خاصی نمیشه و هر زبان شی گرایی میتونه پیاده سازیش بکنه. این مثال رو ببینید.class Logger {
    void logAll() {
        print(&amp;quotLogger.logAll()&amp;quot);
    }
}

class Controller {
    private Logger logger;

    public Controller(Logger logger) {
        this.logger = logger;
    }

    void logAll() {
        logger.logAll();
    }
}

class Delegation {
    public static void main(String[] args) {

        Logger logger = new Logger();
        Controller controller = new Controller(logger);

        controller.logAll();           // ==&gt; Logger.logAll()
    }
}این مثال به زبان جاواست. مشخص  هم هست که از هیچ ویژگی خاصی توی جاوا استفاده نکردیم.کلاس Controller، یکی از عملکردهاش رو از کلاس Logger گرفته که در اینجا نوشتنِ لاگ هست. اینجا با صدا زدن متد ()logAll از Controller کد معادلش توی Logger اجرا میشه.برای کامل تر شدن پیاده سازی میتونیم به جای کلاس Logger یک اینترفیس Logger داشته باشیم که کلاس Controller و کلاس هایی مثل FileLogger یا ConsoleLogger اون رو پیاده سازی بکنن.کد زیر رو ببینید.interface Logger {
    void logAll();
}

class FileLogger implements Logger {
    @Override
    public void logAll() {
        File logFile = new File&#40;&amp;quot/path/to/logFile.txt&amp;quot&#41;;
        FileWriter fileWriter = new FileWriter(logFile);
        fileWriter.write(&amp;quotFileLogger.logAll()&amp;quot);
    }
}
class ConsoleLogger implements Logger {
    @Override
    public void logAll() {
        print(&amp;quotConsoleLogger.logAll()&amp;quot);
    }
}

class Controller implements Logger {
    private Logger logger;

    public Controller(Logger logger) {
        this.logger = logger;
    }

    @Override
    public void logAll() {
        logger.logAll();
    }
}

class Delegation {
    public static void main(String[] args) {

        Logger fileLogger = new FileLogger();
        Logger consoleLogger = new ConsoleLogger();

        new Controller(fileLogger).logAll();
        new Controller(consoleLogger).logAll();
    }
}میبینید که برای پیاده سازی یک Delegation ساده توی جاوا چند خط کد باید زده بشه. فرض کنید اگر logger چندتا متد دیگه هم داشت یا توی Controller  قرار بود چند تا  delegation دیگه هم اضافه بشه ، اونوقت چقدر کد توی controller برای پیاده سازی باید اضافه میشد.به همین دلیل بعضی از زبان ها اومدن این کار رو داخل خود زبان انجام دادن و برنامه نویس رو برای زدن کدهای تکراری و خسته کننده معاف کردن.پیاده سازی در سطح زبانبر خلاف جاوا ، کاتلین از Delegation به عنوان یکی از ویژگی های زبان پشتیبانی میکنه.قسمت Controller و Main برنامه ی کد بالا برای کاتلین به این شکل میشه.class Controller(logger: Logger) : Logger by logger

fun main() {
    Controller(ConsoleLogger()).logAll()
}میبینید که برای اضافه کردن عملکرد Logger به کلاس Controller فقط کافیه از &#x60;by&#x60; بعد از تعریف کلاس استفاده کنیم. که هم خیلی راحت هست و هم خیلی خلاصه.از ویژگی های خوب این روش اینه که دیگه لازم نیست خودمون اینترفیس Logger رو برای کلاس Controller پیاده سازی کنیم. چون این کار توسط کامپایلر در زمان کامپایل انجام میشه.اگر هم در آینده قرار شد Controller ما عملکرد دیگه ای هم بهش اضافه بشه، مثلا عملکرد Repository رو هم داشته باشه، تفاوتی که در این حالت خواهیم داشت اضافه کردن یه عبارت by دیگه به شکل زیر خواهد بود.class Controller(logger: Logger, repository: Repository) : Logger by logger, Repository by repositoryبرای این که یک مثال قابل اجرا توی مرورگرتون ببینید میتونید روی این لینک کلیک کنید.https://pl.kotl.in/_c09AA32uاما مبحث Delegation توی کاتلین اینجا تموم نمیشه. به این چیزی که صحبت کردیم Class Delegation گفته میشه .کاتلین یه Delegation دیگه هم داره با عنوان Delegated Properties Delegated Propertiesسعی میکنم با یک مثال توضیح بدم. فرض کنید یه مقداری داریم که می خواهیم فقط یک بار محاسبه بشه و بعد از اون اگر دوباره جای دیگه ای بهش نیاز داشتیم همون مقداری که محاسبه شده، برگرده. به عبارت دیگه متغییر ما Lazy باشه.کدی که براش میزنیم شبیه اینه :var lazyValue: String? = null
    get() {
        if (field == null) {
            field = &amp;quotlazyValue&amp;quot
        }
        return field
    }ولی با کمک کاتلین و استفاده از مفهوم Property Delegation میتونیم این کار رو به زبان واگذار کنیم.val lazyValue: String by lazy {
    &amp;quotlazyValue&amp;quot
}مثال قابل اجراش رو هم اینجا براتون گذاشتم.https://pl.kotl.in/tmFUu9mqvفکر میکنم این معروفترین Delegate توی کاتلین باشه. چند تا مورد دیگه هم هستن که توسط کاتلین تعریف شدن. که سعی میکنم به صورت خیلی خلاصه تعریف شون کنم.ObservableVetoableNotNullObservableمشخص هست که برای پیاده سازی پترن observer ازش میتونیم استفاده کنیم.var observable by Delegates.observable(&amp;quotinitialValue&amp;quot) { property, oldValue, newValue -&gt;
    println(newValue)
}کد قابل اجراش رو اینجا ببینید.https://pl.kotl.in/tmFUu9mqvVetoableاز vetoable زمانی استفاده میشه که قبل از اینکه مقداری رو set کنیم شرط های ما رو باید داشته باشه. مثلا میگیم اگر مقدار جدید اومد در صورتی قبولش کن که بزرگتر از 10 باشه.var vetoable by Delegates.vetoable(100, { property, oldValue, newValue -&gt;
    newValue &gt; 10
})NotNullvar notNull by Delegates.notNull&lt;String&gt;()با این Delegate دیگه در زمان کامپایل لازم نیست از عملگر (?.) Safe Access بعد از نام متغییر استفاده کنیم. فقط باید حواسمون باشه اگر قبل از set کردن مقدارش ، بخواهیم ازش استفاده کنیم، خطای IllegalStateException میگیریم.این ها مواردی بود که خود کاتلین به صورت پیش فرض پشتیبانی می کرد. جدای از این موارد خودتون هم میتونید Delegation property های خودتون رو تعریف کنید.جمع بندیکاتلین سعی کرده تا برنامه نویس ها علاوه بر واضح بودن، کدهای خلاصه تری هم بزنن. به نظر میرسه خیلی هم خوب موفق شده. اینجا هم دیدیم که Delegation باعث شد تا با تعداد خط های کمتر، کدی بنویسیم که هم Reusable باشه و هم Clean.خیلی خوشحال میشم در صورتی که این نوشته رو دوست داشتید ❤️ کنید یا نظرتون را از طریق کامنت برام بنویسید.</description>
                <category>مجتبی حدادی</category>
                <author>مجتبی حدادی</author>
                <pubDate>Tue, 03 Dec 2019 10:09:01 +0330</pubDate>
            </item>
                    <item>
                <title>حل مشکل Gradle برای دانلود از مخازن تحریم شده با راه اندازی Nexus Repository Manager ، یک بار برای همیشه!</title>
                <link>https://virgool.io/@mojtabaha/%D8%AD%D9%84-%D9%85%D8%B4%DA%A9%D9%84-gradle-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AF%D8%A7%D9%86%D9%84%D9%88%D8%AF-%D8%A7%D8%B2-%D9%85%D8%AE%D8%A7%D8%B2%D9%86-%D8%AA%D8%AD%D8%B1%DB%8C%D9%85-%D8%B4%D8%AF%D9%87-%D8%A8%D8%A7-%D8%B1%D8%A7%D9%87-%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C-nexus-repository-manager-%DB%8C%DA%A9-%D8%A8%D8%A7%D8%B1-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%87%D9%85%DB%8C%D8%B4%D9%87-avpkmgcsgglr</link>
                <description>همونطوری که میدونید Gradle برای اینکه بتونه پروژه ما رو بیلد کنه، باید نیازمندی های پروژه (Dependency) رو از مخازنی که براش تعریف کردیم (Repository) دانلود بکنه.برای مثال فرض کنید ما کتابخونه Gson رو نیاز داریم که توی ()mavenCentral موجوده.پس توی فایل build.gradle همچین چیزهایی خواهیم داشت.allprojects {
    repositories {
        mavenCentral()
    }
}

dependencies {
    implementation &#039;com.google.code.gson:gson:2.8.5&#039;
}حالا وقتی که پروژه مون رو بیلد میکنیم، Gradle میره اینجا , و فایل gson-2.8.5.jar رو پیدا میکنه و دانلودش میکنه.ولی خب ما تحریمیم و دسترسی نداریم به این فایل! پس بیلد متوقف میشه !!برای حل مشکل هم که مشخصه باید تحریم ها رو دور بزنیم. که توی این مطلب در موردش به صورت کامل توضیح داده شده. روش هایی مثلتنظیم Proxy تغییر DNSاما یه مشکلاتی این روش ها دارند.مثلا اینکه همیشه ازشون خیالت راحت نیست و زمانی که نیاز داری ریلیز بدی کار نمیکنن و پدر اعصابت رو درمیارن! (خودم زیاد درگیر این مورد بودم)یا اگر یک تیم باشید که روی یک پروژه کار میکنید بعد از این که یکی از اعضای تیم یک Dependency رو اضافه میکنه یا اون رو آپدیت میکنه بدبختی اعضای دیگه تیم برای دانلود اون فایل شروع میشه :)یا شرکتی که مصرف اینترنت کارکنان براش مهم باشه به دلیل اینکه فایل ها توسط هر سیستم دانلود میشن میزان حجم دانلود از اینترنت بالا میره.خب راه حل چیه ؟راه اندازی یک مخزن شخصی (Private Repository)شرکت Sonatype یک Repository manager رایگان به نام Nexus داره که کارش راه اندازی مخزن شخصی روی سیستم خودمون هست.کاری که ما قراره توسط Nexus انجام بدیم به این شکله که درخواست های دانلودی که Gradle داره، به جای اینکه مثلا به ()mavenCentral بره اول به مخزن شخصی ما میره و در صورتی که  اون فایل رو داشته باشیم در اختیار Gradle قرار میگیره و در غیر این صورت توسط مخزن ما دانلود میشه و بعدش تحویل Gradle داده میشه و یک نسخه برای دفعات بعدی نگه داری میشه. تقریبا اتفاقی شبیه عکس پایین.قسمت Local Repository همون مخزن شخصی ماست.از این به بعد بقیه اعضای تیم نیازی به دانلود اون فایل از اینترنت ندارن و کافیه از طریق شبکه Local به مخزن شخصی ما وصل بشن.خب شروع میکنیمبرای این کار نیاز داریم تا Nexus Repository Manager OSS رو دانلود و راه اندازی بکنیم. پس اگر ویندوزی هستیم به این صفحه میریم و ایمیل مون رو وارد میکنیم و فایل رو دانلود میکنیم.(نیاز به دور زدن تحریم داریم)اگر مشکلی برای دانلود دارید من آخرین ورژن (3.17.0) رو که برای ویندوز 64 بیت دانلود کردم و اینجا گذاشتمش.* برای Linux , Mac هم قابلیت راه اندازی وجود داره که اینجا در مورد مراحل ویندوز صحبت میکنیم.حالا فایل فشرده دانلود شده رو Extract میکنیم و به مسیر زیر میریم.extract place ==&gt; nexus-3.17.0-01-win64 ==&gt; nexus-3.17.0-01 ==&gt; bin اونجا cmd یا powerShell رو باز میکنیم و دستور run رو به این شکل اجرا میکنیم..\nexus.exe /runحواستون باشه اواسط کار پیغامی میاد برای دادن دسترسی به اینترنت که شما باید allow access رو بزنید.حالا منتظر میمونیم تا این پیغام رو روی صفحه ببینیم.تبریک میگم. به همین سادگی repository manager تون راه اندازی شد.حالا مرورگر وب تون رو باز کنید و به این آدرس برید.  http://localhost:8081/بعد به منوی Browse برید. میبینید که اولین آیتم اون لیست maven-central هستش که با نوع Proxy به صورت پیش فرض تعریف شده و جلوش یک دکمه ی کپی وجود داره. دکمه کپی رو بزنید تا دیالوگی که داخلش آدرسی شبیه آدرس زیر میاد رو ببینید.http://localhost:8081/repository/maven-central/این آدرس جایگزینی هست که Gradle باید به اون متصل بشه.به صورت زیر به جای ()MavenCentral داخل Repository های پروژه مون تعریفش میکنیم.در انتها فایل مون به این شکل میشه.allprojects {     
     repositories {         
          // comment this line ==&gt; mavenCentral()   
         //add this line 
         maven { url &#039;http://localhost:8081/repository/maven-central/&#039; } 
     } 
 }  و تمام ! اینجا میتونید ویدیوی مراحل بالا رو ببینید https://www.aparat.com/v/Qxt7f حالا از این به بعد Gradle هر Dependency ای رو که لازم باشه از mavenCentral بگیره از سرور واسط ما دریافت میکنه.* فقط نکته ای که وجود داره حواستون باشه اگر دفعه اولی هست که اون Dependency رو از سرور واسط درخواست میکنید. باید روش های قبلی (پراکسی یا تغییر DNS) رو انجام داده باشید. https://www.aparat.com/v/PxL8D اما یه سوالی پیش میاد!سوال : همه ی Dependency های یک پروژه که توی MaveCentral نیست! ممکنه توی Jcenter یا مثلا مخزن Google یا هر جای دیگه ای باشه! تکلیف اونا چی میشه ...؟جواب : خودمون اونها رو اضافه می کنیم.فرض کنید میخواهیم Jcenter رو هم به لیست مخرن های سرور واسط اضافه کنیم.برای این کار، یه بار دیگه وارد مرورگر بشید و به آدرسhttp://localhost:8081/ برید، بالا سمت راست روی لاگین کلیک کنید  اگر اولین باری هست که میخواهید لاگین کنید برای user name مقدار admin رو وارد کنید. و برای پسورد به این مسیر برید.extract place ==&gt; nexus-3.17.0-01-win64 ==&gt; sonatype-work ==&gt; nexus3اینجا یه فایل به نام admin.password وجود داره که رمز admin داخلش وجود داره.اون رو کپی کنید و لاگین کنید. حواستون باشه رمز رو ذخیره کنید. چون بعد از لاگین این فایل پاک میشه.حالا به قسمت settings برید و از منوی کناری Repositories رو انتخاب کنید. با زدن دکمه create repository یک لیست براتون باز میشه که حالت های مختلف ساختن مخازن هست. برای این که Gradle پروتکل های Maven رو میشناسه پس نوع  مخزن مون باید maven 2 باشه و این رفتاری که ما  از مخزن میخاهیم (این که بهش وصل شیم و به عنوان یه آینه عمل بکنه) بهش Proxy گفته میشه. پس از توی لیست (maven 2 (proxy رو انتخاب کنید. تا صفحه ی زیر باز بشه.اینجا وارد جزئیات نمیشم، فقط دوتا فیلد اجباری رو وارد میکنیم.برای مقدار Name مثلا مینویسیم proxy-jcenter-repo و برای remote storage آدرس زیر رو وارد میکنیمhttps://jcenter.bintray.com/شاید براتون سوال پیش بیاد آدرس ریپازیتوری jcenter رو از کجا آوردم؟! که البته چیز خاصی نیست با یه سرچ بهش میرسید.ولی خب راه دیگه ای مثل خودندن داکیومنت ها وجود داره که توی ویدیوی زیر نشونش دادم. https://www.aparat.com/v/YjxWf  حالامثل()mavenCentralکهتوضیحدادمتویbuild.gradleمقدار()Jcenterروبهمقدارزیرتغییرمیدیموتمام. maven {url &#039;http://localhost:8081/repository/proxy-jcenter-repo/&#039;}این کار رو برای همه ی مخزن های پروژه انجام میدیم و در آخر هم با بیلد کردن Gradle همه فایل ها داخل سرور لوکال ما قرار میگیرند و از این به بعد دسترسی به اینترنت نیاز نخواهد بود.فقط یادتون باشه برای دفعات بعد نیاز نیست کار خاصی بکنید و فقط کافیه که Repository تون رو run/ بکنید و بدون هیچ مشکلی بابت Dependency های پروژه به برنامه نویسی خودتون برسید.تنظیم پراکسیاگر نیاز داشتین که برای سرور واسط تون Proxy ست کنید تنها کافیه توی تنظیمات دنبال منوی HTTP بگردید و مثل عکس زیر تنظیمش کنید.تنظیم Proxy خب فکر میکنم آموزش تا همینجا کفایت میکنه و شما هم متوجه اصل موضوع شده باشید.امیدوارم این روش مشکلات تون رو بتونه کاهش بده.اگر سوالی داشتید خوشحال میشم بتونم بهش پاسخ بدم.ممنون از وقتی که گذاشتید.موفق باشید.</description>
                <category>مجتبی حدادی</category>
                <author>مجتبی حدادی</author>
                <pubDate>Sat, 29 Jun 2019 16:22:16 +0430</pubDate>
            </item>
            </channel>
</rss>