Android RxJava Retrofit MVVM RecyclerView не отображается - PullRequest
0 голосов
/ 18 февраля 2019

Я реализую RecyclerView во фрагменте.XML должен быть правильным, так как я попробовал его с жестко закодированными данными, а вызов API действительно возвращает правильные данные json с сервера в соответствии с журналом в консоли.Проблема в том, что адаптер RecyclerView не получает никаких данных из моего Observable.Вот моя реализация

В интерфейсе PostDataService я использовал Retrofit для получения Observable>

interface PostDataService {

    @GET(".")
    fun getPosts(
        @Query(value = "offset") offset: Long = 0,
        @Query(value = "limit") limit: Long = 10,
        @Query(value = "subscribedOnly") subscribedOnly: Boolean = false
    ): Observable<List<Post>>

    companion object {
        val retrofit: PostDataService = Retrofit.Builder()
            .baseUrl("http:aws/api/post/")
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(MoshiConverterFactory.create())
            .client(client)
            .build()
            .create(PostDataService::class.java)
    }
}


В PostListRepository я использовал операторы RxJava для получения LiveData

class PostListRepository {

    private val postListLiveData: MutableLiveData<List<Post>> = MutableLiveData()
    private val compositeDisposable: CompositeDisposable = CompositeDisposable()

    fun getPostListLiveData(): MutableLiveData<List<Post>> {
        val postList: MutableList<Post> = ArrayList()
        val retrofitInstance = PostDataService.retrofit
        val postListObservable = retrofitInstance.getPosts()
        compositeDisposable.add(
            postListObservable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .flatMapIterable { it }
                .subscribeWith(object : DisposableObserver<Post>() {
                    override fun onError(e: Throwable) {
                        // if some error happens in our data layer our app will not crash, we will
                        // get error here
                    }

                    override fun onNext(post: Post) {
                        postList.add(post)
                    }

                    override fun onComplete() {
                        postListLiveData.postValue(postList)
                    }
                })
        )
        return postListLiveData
    }

    fun clear() {
        compositeDisposable.clear()
    }
}


В PostListViewModel я передал LiveData из репозитория в эту ViewModel.

class PostListViewModel : ViewModel() {

    private var postListRepository: PostListRepository = PostListRepository()

    fun getPostList(): MutableLiveData<List<Post>> {
        return postListRepository.getPostListLiveData()
    }

    fun clear() {
        postListRepository.clear()
    }
}


Вот фрагмент, который содержит RecyclerView.Я думаю, что функция .oberserve в getPostList() не вызывается, так как я попытался Записать ее, но ничего не получил.

class PostListFragment : Fragment() {

    private lateinit var recyclerView: RecyclerView
    private lateinit var swipeLayout: SwipeRefreshLayout
    private lateinit var postListViewModel: PostListViewModel
    private val postListAdapter = PostRecyclerViewAdapter()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.view_post_list, container, false)
        recyclerView = rootView.findViewById(R.id.postRecyclerView)
        recyclerView.apply {
            setHasFixedSize(true)
            addItemDecoration(VerticalSpaceItemDecoration(36))
            layoutManager = LinearLayoutManager(context)
            adapter = postListAdapter
        }

        postListViewModel = ViewModelProviders.of(this).get(PostListViewModel::class.java)
        getPostList()

        swipeLayout = rootView.findViewById(R.id.swipeLayout)
        swipeLayout.setColorSchemeResources(R.color.colorPrimary)
        swipeLayout.setOnRefreshListener {
            getPostList()
            swipeLayout.isRefreshing = false
        }
        return rootView
    }

    override fun onDestroy() {
        super.onDestroy()
        postListViewModel.clear() // to avoid memory leak
    }

    private fun getPostList() {
        postListViewModel.getPostList().observe(this, Observer<List<Post>> { resource ->
            postListAdapter.setPostList(resource)
            postListAdapter.notifyDataSetChanged()
        })
    }
}


Вот адаптер для RecyclerView:

class PostRecyclerViewAdapter : RecyclerView.Adapter<PostViewHolder>() {

    private var postList: List<Post> = ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
        // create a new view
        val postView = PostView(parent.context)
        // set the view's size, margins, paddings and layout parameters
        return PostViewHolder.from(postView)
    }

    override fun getItemCount(): Int = postList.size

    override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
        val curPost = postList[position]
        holder.postView.apply {
            setPostOwnerDisplayName(curPost.content.userDisplayedName)
            setPostOwnerRole(curPost.content.role)
            setPostOwnerAvatar(R.mipmap.ic_launcher_round)
            setPostText(curPost.content.text)
            setPostImage(curPost.content.smallMediaPaths[0])
            setLikeState(curPost.liked)
            setBookmarkState(curPost.bookmarked)
        }
    }

    fun setPostList(postList: List<Post>) {
        this.postList = postList
    }
}

Как я уже упоминал выше, я думаю, что функция .oberserve в getPostList() в PostListFragmentне вызывал, так как я попытался Записать его, но ничего не получил, поэтому в RecyclerView не передаются данные.Может ли кто-нибудь помочь мне найти причину, по которой он не вызывается или почему он не получает данные из ViewModel?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Я только что узнал, что забыл перехватить исключение в RxJava onNext() на случай ошибки сериализации moshi.Получив это, я получил некоторые ошибки преобразования Моши.Разместил это на тот случай, если кто-нибудь небрежно забыл поймать ошибку Моши.Спасибо!

0 голосов
/ 18 февраля 2019

Я бы не подумал, что это связано с вашей проблемой, но у вашего кода есть потенциальные проблемы.

  1. Переместить observe деталь в onActivityCreated было бы лучше, чтобы убедиться, что представление создано.
  2. при повторном создании вашего фрагмента будет добавлен новый Observer, а предыдущий еще жив, потому что ваш Observer является анонимным.Таким образом, вы должны управлять наблюдателями, чтобы предотвратить это.
...