برقراری ارتباط بین Fragment و Activity با استفاده از ViewModel

برقراری ارتباط بین Fragment و Activity با استفاده از ViewModel
فهرست مقاله [نمایش]

    در ماه های اول که تازه برنامه نویسی رو یاد گرفته بودم نمایش لایو داده ها برایم کار بسیار دشوار و پیچیده ای بود و خیلی کدهای گیج کننده ای می نوشتم اما با مطالعه چندین مقاله یاد گرفتم که با استفاده از فرگمت این کار رو خیلی راحت و بدون دردسر میتوانم انجام بدهم و میخوام استفاده این روش رو با شما به اشتراک بذارم.

    ارتباط یکی از مهمترین مباحث برای توسعه دهندگان است و از بسیاری جهات قابل انجام است. اما نکته مهم این است که این کار را ساده و بهینه انجام دهیم ما می توانیم این کار را با استفاده از static filed انجام دهیم اما مشکل حافظه رخ می دهد. برای جلوگیری از مشکل حافظه، بسیاری از توسعه دهندگان کارهایی مانند

    (activity as MainActivity).passDataToAnotherFragment()

    انجام میدهند

    آیا با این روش مشکلی  وجود دارد؟

    این fragment را با یک activity خاص متصل می کند، قابلیت استفاده مجدد را کاهش می دهد.

    پس این روش توصیه شده چیست؟

    گوگل توصیه می کند ازinterface (قبل از ViewModel) استفاده کنید. برای این کار ما باید در کلاس Activity آن interface را پیاده سازی کنیم Child fragments یک reference از interface اجرا شده توسط Activity را نگه می دارد. داده ها از طریق متد های interface منتقل می شوند.

    fragment- activiti

     

     

     

     

     

     

     

     

     

     

     

    بگذارید یک سناریوی ساده را در نظر بگیریم که در آن دو fragment تحت یک activity وجود دارد ، یکی برای وارد کردن یک شماره و دیگری نشان دادن دو برابر ورودی Activity همچنین پیامی را نشان می دهد مثلا ورودی شما 137 است.

     

    shared view model

     

     

     

     

     

     

     

     

    آیا می توانید تصور کنید که چه کدی و چند سناریو را باید بنویسیم؟

    من به جزئیات آن نمی پردازم زیرا این مقاله در مورد ساده ترین راه حل صحبت می کنم نه نشان دادن اجرای interface

    راه آسان 

    در اینجا ViewModel آمده است تا ما را از دستیابی به سناریوهای زیادی و اجرای interface نجات دهد. ما فقط نیاز به ایجاد کلاس ViewModel داریم ویک instance در fragment ایجاد می کنیم اما Activity Scope استفاده می کنیم تا همه fragment های مربوط به Activity از جمله خود Activity در دسترس باشد.

    Communicate between Fragment and Activity using ViewModel

     

    جریان کاری ارتباطات با استفاده از ViewModel

     

    یک کلاس ViewModel ایجاد کنید

    class SharedViewModel:ViewModel(){
        val inputNumber = MutableLiveData<Int>()
    }
    

     

    برای انتشار یا انتقال داده ها از fragment ورودی ViewModel را در Activity Scope ایجاد می کنیم. برای این کار activity reference را به عنوان argument از ()ViewModelProvides.of بگذرایم. متد Noe فقط داده ها را به شیء ViewModel مانند این منتقل می کند.

    activity?.let {
        sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel::class.java)
    }
    
    et_input.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(p0: Editable?) {}
    
        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    
        override fun onTextChanged(txt: CharSequence?, p1: Int, p2: Int, p3: Int) {
            txt?.let {
                var input = 0
                if (txt.toString().isNotEmpty()) {
                    input = txt.toString().toInt()
                }
    
                sharedViewModel?.inputNumber?.postValue(input)
            }
        }
    

     

    در Activity ما فقط باید نمونه ای از ViewModel خود ایجاد کنیم و داده های مورد نیاز را مشاهده کنیم.

    val sharedViewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
    
    sharedViewModel.inputNumber.observe(this, Observer {
        it?.let {
            // do some thing with the number
        }
    })
    
    

    حالا fragment خروجی چطور است؟

    برای مشاهده داده ها می توانیم برای fragment خروجی نیز همین کار را انجام دهیم. اما بخاطر داشته باشید که ما باید درActivity Scope، نمونه ViewModel را ایجاد کنیم ، در غیر اینصورت اندروید به جای به اشتراک گذاشتن نمونه مشابه، نمونه جداگانه ایجاد می کند و ما داده ها را دریافت نمی کنیم.

    برای fragment خروجی این کار را انجام می دهیم

    activity?.let {
        val sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel::class.java)
    
        sharedViewModel.inputNumber.observe(this, Observer {
            it?.let {
                // do some thing with the number
            }
        })
    }
    

     

    کد های این آموزش را میتوانید از لینک زیر دانلود کنید.

    https://github.com/maysambabaei/Fragment_viewmodel


    • نویسنده: میثم بابائی

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران

    avatar
    پیمان
    1399/04/26

    تا اون قسمتی که یه کلاس ویومدل تعریف می کنیم درسته ولی  اگر بعدش به صورت زیر باشه بهتره

    یعنی لازم نیست که ما داخل اکتیویتی چیزی تعریف کنیم که خودش وابستگی ایجاد می کنه و بهتره این کار نشه

    فقط کافیه داخل فرگمنت کد زیر رو بزنیم تا لایف سایکل viewModel به اکتیویتی وصل بشه

    ()private val mViewModel: MyViewModel by activityViewModels

    یا راه بهتر وصل کردن اون به یه navGraph است که بهتر و بهینه تر است مثل کد زیر

    private val mViewModel: MyViewModel by navGraphViewModels(R.id.my_nav_graph)

    
     

    *قسمت نمایش کدهای سایت هم درست نشون داده نمی شن که اگر direction رو به ltr  کنید درست می شه