>

Android 개발자의 페이징 라이브러리 개요 를 따르고 있습니다. DataSource.Factory 를 사용하는  다음 방법으로 데이터베이스에서 데이터를 가져옵니다.

@Dao
interface ConcertDao {
    // The Int type parameter tells Room to use a PositionalDataSource
    // object, with position-based loading under the hood.
    @Query("SELECT * FROM Concerts ORDER BY date DESC")
    fun concertsByDate(): DataSource.Factory<Int, Concert>
}

그러나 내 경우에는 테이블 Concert가 없지만 다른 방법으로 값을 저장하는 ConcertAA 테이블이 있습니다.

예를 들어, 내 Concert  수업은 :

data class Concert(val date: Long, val bands: List<Band>)

ConcertAA  활성 Android 수업은 다음과 같습니다.

@Table(name = "Concerts")
class ConcertAA(): Model(){
    @Column(name = "Bands")
    var bands: String? = null
    @Column(name = "Date", index = true)
    var date: Long? = null
}

밴드를 Json String으로 저장하는 곳

따라서 나의 질문은 어떻게 내가 ConcertDao 를 갖는가이다  쿼리 시점에 내 데이터베이스에 대해 각 ConcertAA 를 변환합니다.   Concert 에 개체  리스트에서 사용될 객체? 쿼리 SELECT * FROM Concerts ORDER BY date DESC 이후   ConcertAA 목록을 반환합니다   Concert 의 목록이 아닙니다 .


  • 답변 # 1

    다음은 내 자신의 질문에 대답 할지라도 데이터가 변경 될 수있는 데이터베이스 네트워크 논리에 대해서는이 솔루션으로는 이미 데이터베이스에 저장된 데이터의 업데이트를 처리하지 못하기 때문에 충분하지 않습니다.

    추상 클래스의 양을 용서하십시오-나는 보통 확장과 재사용 성을 위해 일합니다. 또한 Java와 Kotlin 코드의 혼합을 용서하십시오. 어떤 이유로 일부 라이브러리는 Kotlin을 사용하는 프로젝트에서 인식되지 않지만 그러한 경우 Kotlin을 자유롭게 사용하십시오.

    기본적으로 우리는 새로운 DataSource 를 만들어야했습니다  수업

    abstract class MyDataSource<Value>: PositionalDataSource<Value>() {
        override fun loadInitial(params: PositionalDataSource.LoadInitialParams, callback: PositionalDataSource.LoadInitialCallback<Value>) {
            callback.onResult(getDataFromDatabase(params.requestedLoadSize, params.requestedStartPosition)?: listOf(), 0)
        }
        override fun loadRange(params: PositionalDataSource.LoadRangeParams, callback: PositionalDataSource.LoadRangeCallback<Value>) {
            callback.onResult(getDataFromDatabase(params.loadSize, params.startPosition)?: listOf())
        }
        abstract fun getDataFromDatabase(limit: Int, offset: Int): List<Value>?
    }
    
    
    구현 된 Concert  데이터 클래스 :

    class ConcertDataSource : MyDataSource<Concert>() {
        override fun getDataFromDatabase(limit: Int, offset: Int): List<Concert>? {
            return ConcertAA.getConcerts(limit, offset)
        }
    }
    
    

    그런 다음 우리는 DataSourceFactory 가 필요합니다  데이터 소스 인스턴스를 생성합니다 :

    abstract class MyDataSourceFactory<Key, Value> : DataSource.Factory<Key, Value>() {
        val mutableLiveData: MutableLiveData<DataSource<Key, Value>>? = null
        override fun create(): DataSource<Key, Value> {
            val dataSource = createDataSource()
            mutableLiveData?.postValue(dataSource)
            return dataSource
        }
        abstract fun createDataSource(): DataSource<Key, Value>
    }
    
    

    ConcertDataSource에 대해 구현 된 DataSourceFactory :

    class ConcertDataSourceFactory : MyDataSourceFactory<Int, Concert>() {
        override fun createDataSource(): DataSource<Int, Concert> {
            return ConcertDataSource()
        }
    }
    
    

    그런 다음 ViewModel   PagedList 를 위해  데이터 소스가 있습니다 :

    public class ConcertViewModel extends ViewModel {
        public final LiveData<PagedList<Concert>> concertList;
        private FetchCallback callback;
        private final int pageSize = 10
        PagedList.BoundaryCallback<Concert> boundaryCallback = new PagedList.BoundaryCallback<Concert>(){
            boolean frontLoaded =false;
            public void onZeroItemsLoaded() {
    //            callback.fetch(...);
            }
            public void onItemAtFrontLoaded(@NonNull Concert itemAtFront) {
                if(!frontLoaded) {
    //                callback.fetch(...);
                }
                frontLoaded = true;
            }
            public void onItemAtEndLoaded(@NonNull Concert itemAtEnd) {
    //            callback.fetch(...);
            }
        };
        public ConcertViewModel(FetchCallback callback) {
            this.callback = callback;
            ConcertDataSourceFactory dataSourceFactory = new ConcertDataSourceFactory();
            PagedList.Config config = new PagedList.Config.Builder()
                    .setPageSize(pageSize)
                    .setInitialLoadSizeHint(pageSize)
                    .setEnablePlaceholders(false)
                    .build();
            concertList = new LivePagedListBuilder<>(dataSourceFactory, config).setBoundaryCallback(boundaryCallback).build();
        }
        public void refresh() {
            conertList.getValue().getDataSource().invalidate();
        }
    }
    
    

    우리는 BoundaryCallback 를 사용한다  PagedList가 목록의 어느 한쪽에 도달 할 때마다 더로드해야하고 데이터베이스 데이터에 추가 데이터가 저장되어 있지 않을 때마다 들어야합니다. 그러면 서버 (또는 모든 데이터 공급자)에서 더 많은 데이터를 가져올 수 있습니다. 가져 오기는 맞춤 콜백을 사용하여 호출됩니다.

    interface FetchCallback{
        fun fetch(limit: Int?, concertIdOffset: String?)
    }
    
    

    이제 ViewModel 에 콜백을 전달해야하므로 우리는 ViewModelProviders 에 알려야합니다   ViewModel 의 새 인스턴스를 만드는 방법  매개 변수와 함께. 이것은 ViewModelProvider.Factory 를 사용하여 수행됩니다. :

    abstract class MyViewModelFactory(
            private val callback: FetchCallback) : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return createViewModel(callback)
        }
        abstract fun <T : ViewModel> createViewModel(callback: FetchCallback): T
    }
    
    

    구현 된 ViewModelFactory  콘서트 :

    class ConcertViewModelFactory(callback: FetchCallback) : MyViewModelFactory(callback) {
        override fun <T : ViewModel> createViewModel(callback: FetchCallback): T {
            return ConcertViewModel(callback) as T
        }
    }
    
    

    마침내, 우리는 ViewModel 를 초기화합니다  우리의 관점에서 ( Activity Fragment 등) :

    val factory = ConcertViewModelFactory(
                object: FetchCallback{
                    override fun fetch(limit: Int?, eventIdOffset: String?, level: RequestParameters.RequestLevel, showLoader: Boolean) {
                        //Do the call to the server
                    }
                })
        viewModel = ViewModelProviders.of(this, factory).get(ConcertViewModel::class.java)
        adapter = ConcertAdapter()
        viewModel.concertList.observe(viewLifecycleOwner, Observer(adapter::submitList))
    
    

    이것은 내 질문에 대한 답이 될 것이지만 (적어도 지금은) 안드로이드 용 페이징 라이브러리는 가변 데이터를 처리하지 않습니다. 예를 들어, 콘서트에 변경할 수있는 밴드 목록이있는 경우 (예 : 밴드 중 하나가 콘서트에이를 수없는 경우) 로직은 데이터베이스에 저장된 데이터를 업데이트 할 때 서버에 추가 데이터를 요청하기 때문에 데이터베이스에 저장된 데이터를 업데이트 할 수 없습니다 데이터베이스에 저장된 데이터의 경계 (상단 또는 하단) 중 하나에 도달합니다. 따라서 내 목적으로이 라이브러리는 쓸모가 없습니다.

  • 이전 python - pycharm - 통역사 작성 실패 오류 발생 : 권한 거부 :윈도우 10
  • 다음 python - 사전 (람다가 아님)을 사용하여 사전 목록에서 dict 값 업데이트