-1

私はPaging LibraryとAndroid Architecture Componentsを使用しています。私はpagedlistのlivedataを観察し、変更があったときにRecyclerViewを更新したいだけです。PagedListデータを観察するには?

私のViewModelで作成され、私の断片で観察されるMediatorLiveDataオブジェクトであるisLoadingLiveData、isEmptyLiveData、およびerrorLiveDataオブジェクトを観察しています。また、リモートから取得したGistリストを返すresultLiveDataを観察します。

私のViewModelでは、PagedList LiveDataを作成しました。データが変更されたときは、isLoadingLiveData、isEmptyLiveData、errorLiveDataおよびPagedListAdapterを更新したいと考えました。したがって、私はisLoadingLiveData、isEmptyLiveData、errorLiveDataおよびresultLiveDataをMediatorLiveDataオブジェクトとして定義しました。これらのオブジェクトのソースとしてresultLiveDataを追加しました。したがって、resultLiveDataが変更された場合、これらのオブジェクトのonChangedメソッドが呼び出されます。 resultLiveDataはuserNameLiveDataに依存するため、userNameLiveDataが変更されると、allGistsLiveDataが呼び出され、データがフェッチされます。たとえば、ユーザーがリストをスワイプすると、userNameLiveDataが設定され、ネットワークコールが再度実行されます。

私のViewModel:

private val userNameLiveData = MutableLiveData<String>() 
private var gists: LiveData<PagedList<Gist>>? = null 

val allGistsLiveData: LiveData<PagedList<Gist>> 
    get() { 
     if (null == gists) { 
      gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0, 
        PagedList.Config.Builder() 
          .setPageSize(PAGED_LIST_PAGE_SIZE) 
          .setInitialLoadSizeHint(PAGED_LIST_PAGE_SIZE) 
          .setEnablePlaceholders(PAGED_LIST_ENABLE_PLACEHOLDERS) 
          .build()) 
     } 
     return gists!! 
    } 

val resultLiveData = MediatorLiveData<LiveData<PagedList<Gist>>>().apply { 
    this.addSource(userNameLiveData) { 
     gists = null 
     this.value = allGistsLiveData 
    } 
} 


val isLoadingLiveData = MediatorLiveData<Boolean>().apply { 
    this.addSource(resultLiveData) { this.value = false } 
} 

val isEmptyLiveData = MediatorLiveData<Boolean>().apply { 
    this.addSource(resultLiveData) { this.value = false } 
} 

val errorLiveData = MediatorLiveData<Boolean>().apply { 
    this.addSource(resultLiveData) { 
     if (it == null) { 
      this.value = true 
     } 
    } 
} 

fun setUserName(userName: String) { 
    userNameLiveData.value = userName 
} 

と私のフラグメント:

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { 
    super.onViewCreated(view, savedInstanceState) 

    viewModel.isEmptyLiveData.observe([email protected], Observer<Boolean> { isVisible -> 
     emptyView.visibility = if (isVisible!!) View.VISIBLE else View.GONE 
    }) 

    viewModel.isLoadingLiveData.observe([email protected], Observer<Boolean> { 
     it?.let { 
      swipeRefreshLayout.isRefreshing = it 
     } 
    }) 

    viewModel.errorLiveData.observe([email protected], Observer<Boolean> { 
     it?.let { 
      showSnackBar(context.getString(R.string.unknown_error)) 
     } 
    }) 

    viewModel.setUserName("melomg") 
    viewModel.resultLiveData.observe([email protected], Observer { it -> gistAdapter.setList(it?.value) }) 
} 


override fun onRefresh() { 
    viewModel.setUserName("melomg") 
} 

私のリポジトリ:

fun getYourGists(userName: String): LivePagedListProvider<Int, Gist> { 
    return remoteDataSource.getYourGists(userName, GitHubApi.getGitHubService(context)) 
} 

私remoteDataSource:

fun getYourGists(username: String, dataProvider: GitHubService): LivePagedListProvider<Int, Gist> { 
    return object : LivePagedListProvider<Int, Gist>() { 
     override fun createDataSource(): GistTiledRemoteDataSource<Gist> = object : GistTiledRemoteDataSource<Gist>(username, dataProvider) { 
      override fun convertToItems(items: ArrayList<Gist>?): ArrayList<Gist>? { 
       return items 
      } 
     } 
    } 
} 

this projectからこのソリューションを作成しようとしました。しかし、私の問題は です。ネットワークコールの応答を待つことなくresultLiveDataが変更されているため、応答の結果は無視され、データが到着する前に私のUIが更新されています。 resultLiveDataは要求前に変更されているため、まだデータはありません。単にpagedlistのlivedataをどのように観察できますか?

+1

'LivePagedListProviderには何も問題ありません。 GistModel()。getYourGists() 'は' LiveData 'を返します。私は 'ArrayList 'であるLivePagedListProviderのデータを監視したいと思っています。問題は、データがリモートから戻ってこないときに、初期化されたときにallGistsLiveDataが変更されていることです。 – melomg

+0

@pskink LivePagedListProviderの実装を表示するために私のリポジトリとremoteDataSourceクラスを追加しました。 – melomg

答えて

0

最後に、私は実用的な解決策を見つけましたが、それが最良の解決策ではないと思います。だから、もしあなたがどんなアイデアを持っていても、躊躇しないでください。私の解決策は次のとおりです。

PagedListのデータをMediatorLiveDataでラップすることを断念しました。私はまだ他のライブデータ(isLoadingLiveData, isEmptyLiveData, errorLiveData)をMediatorLiveDataとして残しましたが、私の要点PagedList LiveDataが初期化されたときにそのソースを追加しました。コードは以下の通りです:

private var gists: LiveData<PagedList<Gist>>? = null 
private val userNameLiveData = MutableLiveData<String>() 
val isLoadingLiveData = MediatorLiveData<Boolean>() 
val isEmptyLiveData = MediatorLiveData<Boolean>() 
val errorLiveData = MediatorLiveData<ErrorMessage>() 

val allGistsLiveData: LiveData<PagedList<Gist>> 
    get() { 
     if (gists == null) { 
       gists = GistModel(NetManager(getApplication()), getApplication()).getYourGists(userNameLiveData.value!!).create(0, 
         PagedList.Config.Builder() 
           .setPageSize(Constants.PAGED_LIST_PAGE_SIZE) 
           .setInitialLoadSizeHint(Constants.PAGED_LIST_PAGE_SIZE) 
           .setEnablePlaceholders(Constants.PAGED_LIST_ENABLE_PLACEHOLDERS) 
           .build()) 


       isLoadingLiveData.addSource(gists) { isLoadingLiveData.value = false } 
       isEmptyLiveData.addSource(gists) { 
        if (it?.size == 0) { 
         isEmptyLiveData.value = true 
        } 
       } 
       errorLiveData.addSource(gists) { 
        if (it == null) { 
         errorLiveData.value = ErrorMessage(errorCode = ErrorCode.GENERAL_ERROR) 
        } 
       } 
      } 
     } 
     return gists!! 
    } 


fun setUserName(userName: String) { 
    isLoadingLiveData.value = true 
    userNameLiveData.value = userName 
    gists = null 
    allGistsLiveData 
} 
関連する問題