تابستون داره تموم میشه ها، فرصت‌ها محدودن کلی آفر جذاب در کمپین تابستون🔥👇
۰ ثانیه
۰ دقیقه
۰ ساعت
۷ ابوالفضل رضایی
ارسال چند ریکوئست و دریافت اونها به صورت جداگانه..
MohammadMoghadasi حل شده توسط MohammadMoghadasi

سلام خدمت استاد و دوستان گرامی.. 

 

استاد یه مبحثی رو گذاشتن برای تمرین که مثلا لیست پربازدیدترین هارو هم با همون یه متد بگیریم..

من این فانکشن رو نوشتم ولی مشکلی که داره اینه که میاد میبینه آخرین ریکوئست چیه و اون رو به لایو دیتا میده و لایو دیتا آخرین ریکوئست رو به ویو برمیگردونه چطوری میتونم بهش بگم تک به تک انجام بده کار رو؟ آیا باید برای هر یه لیست یه فانکشن جدا بنویسم با یه لایو دیتای جدا؟

 

فانکشن گرفتن لیست Product:

fun requestProductLists(sortId: Int): LiveData<List<Product>> {
        if ((sortId == SORT_LATEST) || (sortId == SORT_POPULAR) || (sortId == SORT_PRICE_DEC) || (sortId == SORT_PRICE_ASC)) {
            progressBarLiveData.value = true
            productRepository.getProducts(sortId)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally { progressBarLiveData.value = false }
                .subscribe(object : NikeSingleObserver<List<Product>>(compositeDisposable) {
                    override fun onSuccess(t: List<Product>) {
                        _productLiveData.value = t
                    }
                })
            return productLiveData
        } else throw IllegalArgumentException("sortId must be 'SORT' Field in Product DataClass..!")
    }

اینهم دوتا ریکوئستی که از ویو گرفتم: (من یه متدی نوشتم برای اینکه شاید یکم خلوت‌تر بشه موقع initialize کردن ریسایکلر ویو‌ها که این زیر میزارمش..)

 mainViewModel.requestProductLists(SORT_LATEST).observe(viewLifecycleOwner,{
            initializeRecyclerViews(
                requireContext(),
                latestProductRv,
                RecyclerView.HORIZONTAL,
                it,
                productListAdapter
            )
        })
        mainViewModel.requestProductLists(SORT_POPULAR).observe(viewLifecycleOwner,{
            initializeRecyclerViews(
                requireContext(),
                popularProductRv,
                RecyclerView.HORIZONTAL,
                it,
                productListAdapter
            )
        })

فانکشن ریسایکر ویو (اضافه):

fun initializeRecyclerViews(
        context: Context,
        recyclerView: RecyclerView,
        orientation: Int,
        products: List<Product>,
        adapter: ProductListAdapter
    ) {
        recyclerView.layoutManager =
            LinearLayoutManager(context, orientation, false)
        adapter.products = products as ArrayList<Product>
        recyclerView.adapter = adapter
    }

مشکلی که بود نمیدونستم دقیقا چی سرچ کنم تا بتونم به جوابم برسم.. امیدوارم بتونم اینجا جوابمو بگیرم..:)

یه جواب کوتاهی خودم بدم ولی میخوام که اگه راه دیگه ای وجود داره از این روش استفاده نکنم.. اونم این هستش که متد ریپازیتوری رو با استفاده از یه متد ViewModel پاس بدید به ویو و اونجا روش Observe بشه.. ولی اینطوری باعث شلوغ شدن کدهای ویو میشه و به نظرم بهتره هر کثیف کاری میخوایم بکنیم توی ViewModel باشه..

 

برای مثال:

 

MainViewModel:

fun requestProduct(sortId: Int): Single<List<Product>> {
        return productRepository.getProducts(sortId).doFinally { progressBarLiveData.value = false }
    }

MainFragment:

 mainViewModel.requestProduct(SORT_POPULAR).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : NikeSingleObserver<List<Product>>(mainViewModel.compositeDisposable) {
                override fun onSuccess(t: List<Product>) {
                    initializeRecyclerViews(
                        requireContext(),
                        popularProductRv,
                        RecyclerView.HORIZONTAL,
                        t,
                        productListAdapter
                    )
                }
            })

ولی همونطوری که میبینین ما باید copositeDisposable رو داخل View به متد بدیم که به نظرم اشتباه باشه از نظر معماری..

و دلیل اصلی که میشه از این استفاده نکرد اینکه state دیتا رو نگه نمیداره.. و در صورت رفرش اکتیویتی یا فرگمنت ما دوباره باید ریکوئست بزنیم..

ابوالفضل رضایی ۱۲ دی ۱۳۹۹، ۱۹:۱۶

سلام ابوالفضل جان 

امیدوارم عالی باشین

 

من هنوز به جلسه نرسیدم و نسبت به چالش اطلاعی ندارم

تا فردا/پسفردا خودم رو به جلسه میرسونم و در همین تاپیک شما رو راهنمایی میکنم.

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

 

پوریا شفیعی ۱۲ دی ۱۳۹۹، ۲۰:۵۶

مهرداد جان چون که کامنت‌ها لیمیت داره اینجا برات جوابتو گذاشتم: 

ببین به قول استاد توی معماری سخت گیری دست developer عه.. من ترجیح میدم متد هارو توی ویو Observe نکنم و فقط از لایو دیتا تا حد ممکن استفاده کنم، به علاوه اینکه  کامپوزیت دیسپوزیبل رو نباید توی View به متدمون بدیم به نظرم، از تمیزی کار کم میکنه..
چیز دیگه ای که هست اگه بخوای توی Room ذخیره کنی خیلی خیلی طول میکشه کاربر ویو براش اماده بشه، خودت فرض کن، اول سمت سرور ریکوئست بره، بعد تا میاد بیاد یکم زمان طول میکشه، بعد الان درخواست بدیم توی دیتابیس ذخیره بشه، بعد از دیتابیس فراخونی کنیم.. یه عملیات فاجعه ای میشه توی پرفورمنس به نظرم

ابوالفضل رضایی ۱۳ دی ۱۳۹۹، ۱۵:۰۲

.

ابوالفضل رضایی ۱۴ دی ۱۳۹۹، ۱۸:۰۴

سلام وقت بخیر

منظورتون از تک به تک انجام بده کار رو؟ چیه دقیقا؟

ممنون

MohammadMoghadasi ۰۴ بهمن ۱۳۹۹، ۱۷:۳۲

چنین کاری فکر می‌کنم اشتباه چون فلسفه ی لایو دیتا اینکه که شما یک لایو دیتا بسازی و بیایید بهش گوش کنید تا زمانی که از بین بره اون اون آبجکت. حالا شما میایید و می‌گید دوباره بیا و از همین آبجکت برای من به یک چیز دیگه گوش بده و در نتیجه اون یکی هم دیتا هاش میشه مثل این میشه یک راه حل برای این کار به نظر میاد اینه که بیایید و مجدد یک آبجکت از ویو مدل بسازید و اگر هم بشه ساخت به خیلی سنگین می‌کنه و احتمال مشکل مموری وجود داره در واقع تو دنیای نرم افزار ما بین چیزای مختلف trade off می‌کنیم یعنی الان توی این مسعله اینکه یک آبجکت بسازید مشکل خاصی نیست و اینکه بخواید به جای ساخت یک ویو مدل برای اینکه کد کمتری بنویسید و یک آبجکت از ویو مدل بسازید اینجا ترید آف جالبی نیست به نظرم

 

بهترین پاسخ
MohammadMoghadasi ۰۵ بهمن ۱۳۹۹، ۰۹:۳۲

درود به همه دوستان

من به این شکل عمل کردم کار میکنه و مشکلی هم نداره

class MainFragment : NikeFragment() {
 val mainViewModel:MainViewModel by viewModel()
    val productListAdapter:ProductListAdapter by inject()
    val productListAdapter2:ProductListAdapter by inject()
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {latestProductsRv.layoutManager =
            LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
        latestProductsRv.adapter = productListAdapter
        super.onViewCreated(view, savedInstanceState)
        mainViewModel.productsLiveData.observe(viewLifecycleOwner){
            Timber.i(it.toString())
            productListAdapter.products = it as ArrayList<Product>
        }
        popularProductsRv.layoutManager =
                LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
        popularProductsRv.adapter = productListAdapter2
        super.onViewCreated(view, savedInstanceState)
        mainViewModel.productsLiveData2.observe(viewLifecycleOwner){
            Timber.i(it.toString())
            productListAdapter2.products = it as ArrayList<Product>
        }

 

class MainViewModel(productRepository: ProductRepository, bannerRepository: BannerRepository) : NikeViewModel() {
    val productsLiveData=MutableLiveData<List<Product>>()
    val productsLiveData2=MutableLiveData<List<Product>>()
    val bannersLiveData = MutableLiveData<List<Banner>>()
    init {
        progressBarLiveData.value=true
        productRepository.getProducts(SORT_LATEST)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
            .doFinally { progressBarLiveData.value=false }
                .subscribe(object :NikeSingleObserver<List<Product>>(compositeDisposable){
                    override fun onSuccess(t: List<Product>) {
                        productsLiveData.value = t
                    }
                })
        productRepository.getProducts(SORT_POPULAR)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally { progressBarLiveData.value=false }
                .subscribe(object :NikeSingleObserver<List<Product>>(compositeDisposable){
                    override fun onSuccess(t: List<Product>) {
                        productsLiveData2.value = t
                    }
                })
        bannerRepository.getBanners()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : NikeSingleObserver<List<Banner>>(compositeDisposable) {
                override fun onSuccess(t: List<Banner>) {
                    bannersLiveData.value = t
                }
            })
    }
}

شما هم میتونید تست کنید ببینید جواب میده؟ و اشکالش رو اینجا به اشتراک بزارید

ali asadollahi ۲۱ اسفند ۱۳۹۹، ۱۰:۰۷