viewModel and duplicate data

پرسیده شده
فعالیت 1249 روز پیش
دیده شده 542 بار
0

سلام 

من یک پروژه خبری بر اساس معماری MVVM و زبان کاتلین و RxJava , liveData ساختم.

وقتی لیست خبرها رو می گیرم و وارد جزئیات خبر می شوم و دوباره به فرگمنت لیست خبر برمیگردم  دو تا اتفاق می افتد.

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

دوم اینکه باز به سمت سرور رکوئست می فرستد و دوباره لیست خبرها رو آپدیت می کند.

خب من نمی خوام وقتی برمیگردم به صفحه لیست خبرها دوباره لیست خبرها آپدیت شود.

چه راه حلی پیشنهاد می دهید؟

class NewsViewModel:ViewModel() {
    private val compositeDisposable=CompositeDisposable()
    private var news= MutableLiveData<NewsLab>()
    private val _str= MutableLiveData<String>()
    val str:LiveData<String>
        get() =_str
        
         fun getNews(context: Context):LiveData<NewsLab>{
        LabRetrofit.getInstance(context).news()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : SingleObserver<NewsLab> {
                override fun onSubscribe(d: Disposable) {
                    compositeDisposable.add(d)
                }

                override fun onSuccess(t: NewsLab) {
                  if (t.success){
                      news.value=t
                      Log.i("newsViewModel", t.dataNews!!.get(0).toString())

                  }else{
                      _str.value="خطا"
                  }
                }

                override fun onError(e: Throwable) {
                    _str.value=e.message

                }
            })
        return news
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }

}

 

 

 

فایل پیوست

علی خدری
علی خدری

10 آذر 99

3
حذف شده

سلام و احترام

 

 

قبل از هر چیز پیشنهاد میکنم جلسه وبینار رو مشاهده کنید این موضوع با زبان جاوا (rx,livedata) تدریس شده .اما در زیر راه حل دیگری با کاتلین برای شما قرار میدم.

سناریویی که من در پروژه ها انجام میدم بدین شکل هست(ترکیب کوروتین و رتروفیت و لایو دیتا) که خدمتتون عرض میکنم:

 

۱- نوشتن متد مربوطه (مثلا گرفتن لیست خبر ها)در Repository 

صرفا یک مثال  :(البته من از روش Paging و Hilt استفاده کردم) ولی خب فرقی در اصل مسءله نمیکند.

 

@Singleton
class TaskRepository @Inject constructor(private val taskApi: ITaskApi) {

    fun getSearchResults(query: String)=
        Pager(
            config = PagingConfig(
                pageSize = 20,
                maxSize = 100,
                enablePlaceholders = false
            ),
            pagingSourceFactory = { TaskPagingSource(UTaskApi, query) }
        ).liveData
}

 

 

۲- سپس در ViewModel پیاده سازی موارد مربوطه به صورت livedata (البته من ویو مدلی نوشتم که به صورت پیشفرض سرچ تسک های پیشفرض رو انجام بده که شما اگر میخواهید از این روش استفاده کنید باید بجای سرچ از گرفتن لیست خبر ها این موضوع رو هندل کنید چرا که این مورد صرفا یک مثال هست) :

class TaskViewModel @ViewModelInject constructor(private val repository: TaskRepository) :
    ViewModel() {
    private val currentQuery = MutableLiveData(Default_QUERY_FOR_SEARCH)

    val tasks =currentQuery.switchMap { queryString->
        repository.getSearchResults(queryString).cachedIn(viewModelScope)
    }

    fun searchTasks(query:String){
        currentQuery.value = query
    }

    companion object{
        private const val Default_QUERY_FOR_SEARCH = "Test"
    }
}

۳- سپس پیاده سازی موارد در ویو مدل و observe کردنشان در Fragment:

//---

۴-پیاده سازی کلیک کردن کاربر روی ایتم مربوطه(برای مثال شما خبر مربوطه در adapter):

 

init {
            binding.root.setOnClickListener {
                val position = bindingAdapterPosition
                if (position != RecyclerView.NO_POSITION) {
                    val item = getItem(position)
                    if (item != null) {
                        listener.onItemClick(item)
                    }
                }

            }
        }

 

۵- implements کردن اینترفیسی که در adapter ساختم در Fragment مربوطه که دیتا رو به DetailFragment منتقل کردم :

override fun onItemClick(task: Task) {
        val action = TaskFragmentDirections.actionTaskFragmentToDetailsFragment(task)
        findNavController().navigate(action)
    }

با این روش مشکل شما حل خواهید شد; یعنی وقتی در فرگمنت جزییات back میزنید دیتا از اول از سرور دریافت نمیشود.

اگر هم میخواهید از روش rx استفاده کنید پیشنهاد من به شما دیدن وبینار مربوطه هست که این موضوع تدریس شده.

امیدوارم سر نخ خوبی بهتون داده باشم برای پیاده سازی پروژه تون

سالم و موفق باشید

 

 

 

 

 

 

 

فایل پیوست

پوریا شفیعی

توسط

پوریا شفیعی

11 آذر 99