<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد دوست حق</title>
        <link>https://virgool.io/feed/@dousthagh</link>
        <description>برنامه نویس اندروید و php</description>
        <language>fa</language>
        <pubDate>2026-07-06 16:51:30</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/142148/avatar/Ssawac.png?height=120&amp;width=120</url>
            <title>محمد دوست حق</title>
            <link>https://virgool.io/@dousthagh</link>
        </image>

                    <item>
                <title>استفاده از یک adapter برای recyclerview های مختلف</title>
                <link>https://virgool.io/@dousthagh/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%DB%8C%DA%A9-adapter-%D8%A8%D8%B1%D8%A7%DB%8C-recyclerview-%D9%87%D8%A7%DB%8C-%D9%85%D8%AE%D8%AA%D9%84%D9%81-rxmcpcqggcpl</link>
                <description>برای یک پروژه که تعداد recyclerview هاش زیاد بود داشتم فکر میکردم که چطور میتونم یه adapter بنویسم برای همه ی recyclerview. و هرجا خواستم ازش استفاده کنم.روال کلی به این صورت که یک کلاس اصلی برای recyclerview adapter درست کردم بعد از اونجایی که چند تا متد از اون برای هر recyclerview میتونه شرایط متفاوت داشته باشه رو بصورت abstract method تعریف کردم تا حتما مقدار دهی بشه مثلا item_view هرکدوم از recyclerview ها. یه مثال بخوام ازش بزنم: مثلا فرض کنید یه recyclerview داریم برای محصولان و یکی دیگه برای لیست سفارشات. خب طبیعتا هردوتا ماهیت یکسان که نمایش لیستی از عناوین باشد رو دارند اما تفاوت هایی هم دارند: * یکی باید property خاصی از product entity رو برای عنوان نمایش بده یکی دیگه از order entity، * با کلیک روی هر سطر از این recyclerview مربوط به product به صفحه جزئیات محصول میرود و برای order به صفحه جزئیات order* ممکن است view که برای هر item درنظر گرفته می شود نیز متفاوت باشد. مثلا برای product از product_view و برای order از order_view که با طراحی های متفاوت میتواند باشد.  * ...خب اول یک کلاس درست کردم تا به عنوان کلاس اصلی adapter باشه که اسمش رو گذاشتم BaseRecyclerViewAdapter .abstract class BaseRecyclerViewAdapter&lt;T&gt;(diffCallback: DiffUtil.ItemCallback&lt;T?&gt;, var itemClickListener: RecyclerViewItemClickListener&lt;T&gt;) :
    ListAdapter&lt;T?, BaseRecyclerViewAdapter&lt;T&gt;.AdapterViewHolder?&gt;(
        diffCallback
    ) {


    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): AdapterViewHolder {
        return AdapterViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(getRecyclerViewItem(), parent, false)
        )
    }


    abstract fun getRecyclerViewItem(): Int
    abstract fun onItemGenerated(position: Int, view: View)
    abstract fun bind(itemView: View, entity: T)

    override fun onBindViewHolder(holderSelect: AdapterViewHolder, position: Int) {
        holderSelect.Bind(getItem(position))
        val view = holderSelect.itemView

        holderSelect.itemView.setOnClickListener {
            itemClickListener.(getItemAt(position) as T)
        }

        onItemGenerated(position, view)

    }

    fun getItemAt(position: Int): T? {
        return getItem(position)
    }

    inner class AdapterViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView) {

        internal fun Bind(entity: T?) {
            if (entity != null) {
                bind(itemView, entity)
            }
        }

    }
}توی این کلاس که به صورت abstract تعریف شده نوع پارامتر های ورودی و خروجی از نوع generic type  یا همون T هستند چون نوع های مختلفی رو ممکن به عنوان ورودی بگیره یا خروجی بده ، مثلا یه جا نوع ProductEntity رو میفرستیم تا وقتی تابع getItemAt فراخوانی شد خروجی باید ProductEntity باشه یه جای دیگه OrderEntity رو میخوایم تابع هایی که به عنوان abstract تعریف شدند :: تابع getRecyclerViewItem: خروجی این تابع همان item view هر سطر از recyclerview می باشدتابع onItemGenerated: وقتی هرکدام از item ها ساخته شد چه اتفاقی بیافتدتابع bind: برای bind کردن مقادیر هر سطراگر به ورودی های این کلاس نگاه کنید میبینید که یک ورودی از نوع DiffUtilItemCallback و یک ورودی دیگر از نوع RecyclerViewItemClickListener دارد که یک interface  می باشد. برای تعریف رویداد کلیک که روی هر سطر اتفاق می افتدinterface RecyclerViewItemClickListener&lt;T&gt; {
    fun (entity: T)
}یک کلاس دیگر برای DiffUtil.Itelcallback درست کردم تا تفاوت آیتم ها را بر اساس منطقی که اختصاصا برای هر recyclerview تعریف می شود به عنوان ورودی دریافت می کند. (از Diffutil بیشتر بدانید )در اینجا هم چون برای هر Recyclerview بسته به entity آن منطق مختلفی برای مشخص کردن این تفاوت ها وجود دارد یک کلاس اصلی به اسم BaseDiffCallback درست کردم تا کلاس های DiffUtilCallback ازش ارث بری کنند class ProductAdapter(RecyclerViewItemClickListener: RecyclerViewItemClickListener&lt;ProductEntity&gt;) :
    BaseRecyclerViewAdapter&lt;ProductEntity&gt;(ProductAdapterOnDiffCallback(),
        RecyclerViewItemClickListener) {

    override fun getRecyclerViewItem(): Int {
        return R.layout.view_item_product
    }

    override fun onItemGenerated(position: Int, view: View) {
    }

    override fun bind(itemView: View, entity: ProductEntity) {
        itemView.findViewById&lt;TextView&gt;(R.id.textView).text = entity.title
    }
}خب تا اینجا هر چیزی که مربوط به کلاس های اصلی بود رو توضیح دادم و نوشتم حالا بریم کلاس های فرزند که باید از این کلاس ها ارث بری کنند خب اول باید adapter مربوط به product recyclerview رو بسازیم ولی قبلش نیاز به DiffUtilItemCallback داریم برای product تا به Recyclerview بگیم که منطق تشخصی تفاوت دو آیتم به این صورت است، class ProductAdapterOnDiffCallback : BaseDiffCallback&lt;ProductEntity&gt;() {
    override fun checkItemsTheSame(oldItem: ProductEntity, newItem: ProductEntity): Boolean {
        return oldItem.id == newItem.id
    }

    override fun checkContentsTheSame(oldItem: ProductEntity, newItem: ProductEntity): Boolean {
        return oldItem.title === newItem.title
    }

}
حالا adapter مربوط به product رو میسازیم :class ProductAdapter(RecyclerViewItemClickListener: RecyclerViewItemClickListener&lt;ProductEntity&gt;) :
    BaseRecyclerViewAdapter&lt;ProductEntity&gt;(ProductAdapterOnDiffCallback(),
        RecyclerViewItemClickListener) {

    override fun getRecyclerViewItem(): Int {
        return R.layout.view_item_product
    }

    override fun onItemGenerated(position: Int, view: View) {
    }

    override fun bind(itemView: View, entity: ProductEntity) {
        itemView.findViewById&lt;TextView&gt;(R.id.textView).text = entity.title
    }
}میبینید که اون سه تا تابع abstract رو اینجا override کردم و یادتون نره که  یک view برای هر سطر بسازید و اینکه یک entity برای product به اسم ProductEntity بسازیدو بصورت زیر هم توی fragment یا activity تعریف کردم val categoryAdapter = ProductAdapter(object :
    RecyclerViewItemClickListener&lt;ProductEntity&gt; {
    override fun (entity: ProductEntity) {
        Log.d(&amp;quotasd&amp;quot, entity.toString())
    }

})Github Repository:::    https://github.com/dousthagh/SingleRecyclerViewAdapter</description>
                <category>محمد دوست حق</category>
                <author>محمد دوست حق</author>
                <pubDate>Wed, 26 May 2021 12:59:28 +0430</pubDate>
            </item>
                    <item>
                <title>API چیست</title>
                <link>https://virgool.io/@dousthagh/api-%DA%86%DB%8C%D8%B3%D8%AA-ftd3hvtmcrx5</link>
                <description>سلام . امروز میخوایم درمورد API  (Application Programming Interface) صحبت کنیم . تاحالا فکر کردین بخواین کاری رو انجام بدین ولی سمت سرور باشه ؟ مثلا بخواین از وضعیت آب و هوا توی اپلیکیشنتون استفاده کنید قطعا شما به عنوان برنامه نویس اندروید نمیتونید توی جاوا یا کاتلین کدی بنویسید که وضعیت هوای فردارو بهتون بده . این وظیفه API هاست. اما این API یه کدی سمت سرورِ معمولا با زبان های php,ASP , ... نوشته میشن. که در نهایت یه end pint به شما میدن که با فراخوانی اون میتونید به سرویس دسترسی داشته باشین مثلا آدرس A که با فراخوانی اون بهتون میگه تاریخی که به عنوان متغیر ارسال کردید بهش وضعیت هواش چطوره (آفتابی، بارانی و ... )  بعد شما توی کدهای اندرویدتون بدون اینکه درگیر پیچیدگی پیاده سازی سرویس A بشید میتونین با چند خط کد ساده اونو فراخوانی کنید و ازش استفاده کنیدبرای فراخوانی API توی اندروید میتونید از لایبرری Volley استفاده کنید البته اگر میخواین یکم جذاب تر کار کنید از کتابخانه Retrofit استفاده کنین.راستی یادم رفت بگم خروجی API ها هم معمولا از نوع JSON یا XML که بعد از اینکه اون API رو فراخوانی کردین باید خروجی مثل json رو تبدیل به objectمورد نظر کنید که اون هم با کلاس هایی مثل Gson استفاده کنیدای پی آی ها در حقیقت یک واسط نرم افزاری هستن . </description>
                <category>محمد دوست حق</category>
                <author>محمد دوست حق</author>
                <pubDate>Sun, 17 May 2020 23:11:30 +0430</pubDate>
            </item>
                    <item>
                <title>7 قدم تا برنامه نویسی حرفه ای اندروید</title>
                <link>https://virgool.io/coderlife/7-%D9%82%D8%AF%D9%85-%D8%AA%D8%A7-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%AD%D8%B1%D9%81%D9%87-%D8%A7%DB%8C-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-lscau3obtp2j</link>
                <description>سلام برای اینکه برنامه نویس حرفه ای بشین و کدهایی که میزنید حرفه ای باشد باید چیکار کنیم ؟ میخوام 7 تا از کارهایی که باید خیلی روش وقت بزارین و تمرین کنین تا بتونین برنامه های حرفه ای بنویسین رو توی این پست بگم 1-الگوی طراحی معماری - architecture design patternاوایل که برنامه نویسی رو شروع کرده بودم هرچی که میخواستم بنویسم رو یه جا مینوشتم. هیچ چیزی جای خودش نبود اصلا فکرشو نمیکردم هرچیزی جای خاص خودشو داره تا اینکه رسیدم به نگهداری محصول. کم کم واسم مهم شد که چطور باید یک محصولی که 5 ماه پیش نوشتم رو تغییر بدم یا خطایی داره خطای اونو برطرف کنم توی همین فکر و درگیر با دغدغه های این مدلی بودم که وارد تیم شدم دیدم واقعا به یک ساختار مشخص نیازه تا بتونیم همو بفهمیم یعنی اگر یه روز من نباشم همکارم بخواد یه قسمتی از برنامه رو تغییر بده، بنده ی خدا باید سه روز بگرده ببینه مثلا کلاس مربوط به ساخت جدول A کجاست که بعد تازه بخواد یه فیلد بهش اضافه کنه تا اینکه با الگوهای معماری آشنا شدم. بنظرم واقعا بخش جذاب کدنویسی همین architecture design pattern هاست. بچه هایی که asp کارمیکنن مفهوم mvc رو خوب میدونن زیاد باهاش سر و کار داشتن یا بچه هایی که لاراول کار میکنن . الگوهای معماری که توی اندروید داریم زیادن مثل mvp, mvvm  و ... بنظرم از همه جذاب تر و کاربردی تر mvvm . با الگوی معماری مشخص میشه که view شما کجاست، viewmodel کجاست اصلا چطور باید اینارو بهم وصل کنید و ...  مقاله های زیادی درموردش نوشتن  که پیشنهاد میکنم حتما بخونید (شاید خودم سر فرصت درموردش اینجا نوشتم)2-نامتقارن - asynchronousتا حالا شده بخواین یه کاری انجام بدین کاربر متوجه نشه . مثلا کاربر یه متنی مینویسه میخواین اونو توی یه سرور یه جایی ذخیره کنین. برای اینکه کاربر معطل نشه و بتونه بقیه کاراشو انجام بده و شما اطلاعاتی که میخواینو بدون اینکه کاربر بفهمه ذخیره کنین از روش هایی مثل  asynchronus استفاده کنین در حقیقت یه thread جدا از UI thread در اختیار دارین و باهاش کار خودتونو انجام میدین. کاربر بنده خدا و از همه جا بیخبر مشغول کار با UI thread خودشه :)3-کامپوننت ناوبری - navigation component(خودمونیم فارسیش چقدره سخته )فکر کنم از اسمش مشخصه که چیه. فرض کنید میخواید یه روال چند مرحله رو پیش ببرین . مثلا ثبت نام و mobile authenticationاول از کاربر شماره موبایل رو میگیرین مرحله بعد ازش میخواین کد پیامک شده رو وارد کنهمرحله سوم هم در صورت درست بودن کد اطلاعات فردی رو ازش میخواین وارد کنه مراحل این مدلی که معمولا با یه دکمه next هم پیشروی میکنن و از stepper استفاده میشه بهش میگن navigation component . میتونید توی material.io درمورد stepper بیشتر بخونید.4-روم - Roomرسیدیم به قسمت شیرین ماجرا . دومین موردی که من خیلی دوسش دارم بعد mvvm و به شدت ذوق استفاده ازش دارم Room حالا این روم چیه که اینقدر دوسش دارم ؟ بنظرم قبل از اینکه سراغ روم برید بهتره یه سرچی در مورد model کنید. setter, getter چیه درک روم رو راحت تر میکنه . روم یک لایبرری اندروید برای ارتباط با دیتابیس و کدنویسی راحت تره اونه . که توضیحش مفصله ولی پیشنهاد میکنم درموردش بخونید. کد نویسی کلاس های مربوط به db خیلی راحت تر میکنه.5- تست - Testتست کردن اپلیکیشن و نوشتن یه unit test میتونه خیلی کمک کنه تا مطمئن بشین کلاسی که اضافه/حذف/تغییر دادین مشکلی توی روند برنامه تون پیش نیاورده باشه. 6-تزریق وابستگی - Dependency Injectionخلاصه بگم . یکی از مواردی که باید رعایت کنیم اینه کلاس هایی که توی پروژه تعریف میکنیم باید ارتباط کمی با هم داشته باشن یعنی اگر من خواستم یه کلاسی رو تغییر بدم توی 5 تا کلاس دیگه شبیه دومینو مشکل پیش نیاد. برای به حداقل رسوندن این وابستگی از interface استفاده میشه (interface هم جز موارد جذاب کد نویسیه). اگر DI درست پیاده سازی بشه خیلی خوب ولی اگر درست پیاده سازی نشه میتونه خیلی بد باشهاز جمله کتابخانه هایی که توی اندروید این پیاده سازی رو راحت میکنه dagger, dagger2 میباشد.7-کمبود حافظه - Memory Leakهمانطور که از اسمش مشخص است یکی از دغدغه های اصلی مدیریت حافظه است تا این مشکل رخ ندهد. خوشبختانه زبان های  garbage collection language مثل جاوا مدیریت حافظه رو انجام میدن ولی خب یه وقتایی حافظه به صورت منطقی ممکن است leak  شود حالت های مختلفی وجود داره که توی این مقاله جاش نیست که خیلی بهش بپردازیم ولی خب مقاله های زیادی در موردش نوشته شده که میتونید مطالعه کنید . ولی یه لایبرری جالبی دیدم که memory leak پیدا میکنه و کمکتون میکنه تا این مشکل حل کنید. لینک گیت هابشو میذارم Leak Canary GitHub&quot; خب این 7 مورد هم تموم شد . خیلی وقت بود تصمیم داشتم توی ویرگول بنویسم ولی بنظرم کار جذابی نمیومد همیشه خواننده بودم اما با خودم گفتم خیلی زشته آدم همیشه مصرف کننده باشه :) ببخشید اگر خوب ننوشتم و چشاتون اذیت شد و ذهنتون درگیر متوجه شدن جملات نامرتبم شد اولین بار بود.ولی خودمون حس خوبیه نوشتن ;) . خوشحال میشم نظرتون بدونم  &quot; </description>
                <category>محمد دوست حق</category>
                <author>محمد دوست حق</author>
                <pubDate>Sun, 17 May 2020 09:06:25 +0430</pubDate>
            </item>
            </channel>
</rss>