自定义TiledDataSource与分页库

时间:2017-11-02 08:28:53

标签: java android android-room android-architecture-components android-paging

我尝试使用自定义TiledDataSource来使用分页库。当我使用LivePagedListProvider类似于我的Dao方法的返回类型时,它工作正常(在更新表项后 - ui自动更新)。

@Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC")
LivePagedListProvider<Artist> loadArtists();

但是当我尝试为TiledDataSource表更新实现自定义LivePagerListProvider时,没有触发我的观察者。

抽象泛型类:

    public abstract class PagedNetworkBoundResource<ResultType, RequestType> extends TiledDataSource<ResultType> {

    @Override
    public int countItems() {
        return DataSource.COUNT_UNDEFINED;
    }

    @Override
    public List<ResultType> loadRange(int startPosition, int count) {
        fetchFromNetwork(startPosition, count);
        return loadFromDb(startPosition, count);
    }

    @WorkerThread
    private void fetchFromNetwork(int startPosition, int count) {
        if (createCall(startPosition, count) != null)
            try {
                Response<RequestType> response = createCall(startPosition, count).execute();
                if (response.isSuccessful() && response.code() == 200) {
                    saveCallResult(response.body());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    @WorkerThread
    protected abstract void saveCallResult(@NonNull RequestType item);


    @WorkerThread
    protected abstract List<ResultType> loadFromDb(int startPosition, int count);

    @WorkerThread
    protected abstract Call<RequestType> createCall(int startPosition, int count);

    public LiveData<PagedList<ResultType>> getAsLiveData() {
        return new LivePagedListProvider<Integer, ResultType>() {
            @Override
            protected DataSource<Integer, ResultType> createDataSource() {
                return PagedNetworkBoundResource.this;
            }

        }.create(0, new PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setPageSize(20)
                .setInitialLoadSizeHint(20)
                .build());
    }
}

我的dao方法适用于这种情况:

@Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC LIMIT (:limit) OFFSET (:offset)")
List<Artist> loadArtists(int offset, int limit);

我更新Table.States.PLAY_STATE

 public void updatePlayerState(PlayerStateEntity state){
        new Thread(() -> {
            dao.deleteState();
            dao.insertState(state);
        }).run();
    }


 @Dao
public interface PlayStateDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertState(PlayerStateEntity playEntity);

    @Query("DELETE FROM " + Table.States.PLAY_STATE)
    void deleteState();

    @Query("SELECT * FROM "+Table.States.PLAY_STATE)
    PlayerStateEntity getPlayerState();
}

@Entity(tableName = Table.States.PLAY_STATE)
public class PlayerStateEntity extends IdEntity {

    @ColumnInfo(name = "album_played_id")
    private Long albumPlayedId = -1L;

    @ColumnInfo(name = "track_played_id")
    private Long trackPlayedId = -1L;

    @ColumnInfo(name = "artist_played_id")
    private Long artistPlayedId = -1L;


    @ColumnInfo(name = "state")
    private PlayingState state;

    @ColumnInfo(name = "playing_type")
    private PlayingType playingType;

    public Long getAlbumPlayedId() {
        return albumPlayedId;
    }

    public void setAlbumPlayedId(Long albumPlayedId) {
        this.albumPlayedId = albumPlayedId;
    }

    public Long getTrackPlayedId() {
        return trackPlayedId;
    }

    public void setTrackPlayedId(Long trackPlayedId) {
        this.trackPlayedId = trackPlayedId;
    }

    public Long getArtistPlayedId() {
        return artistPlayedId;
    }

    public void setArtistPlayedId(Long artistPlayedId) {
        this.artistPlayedId = artistPlayedId;
    }

    public PlayingState getState() {
        return state;
    }

    public void setState(PlayingState state) {
        this.state = state;
    }

    public PlayingType getPlayingType() {
        return playingType;
    }

    public void setPlayingType(PlayingType playingType) {
        this.playingType = playingType;
    }
}

 class Artist extends PlayEntity{
    private String name;
    private String link;
    private String picture;
    @ColumnInfo(name = "picture_small")
    private String pictureSmall;
    @ColumnInfo(name = "picture_medium")
    private String pictureMedium;
    @ColumnInfo(name = "picture_big")
    private String pictureBig;
    @ColumnInfo(name = "picture_xl")
    private String pictureXl;
    private Boolean radio;
    private String tracklist;
    private Integer position;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public String getPicture() {
        return picture;
    }

    public void setPicture(String picture) {
        this.picture = picture;
    }

    public String getPictureSmall() {
        return pictureSmall;
    }

    public void setPictureSmall(String pictureSmall) {
        this.pictureSmall = pictureSmall;
    }

    public String getPictureMedium() {
        return pictureMedium;
    }

    public void setPictureMedium(String pictureMedium) {
        this.pictureMedium = pictureMedium;
    }

    public String getPictureBig() {
        return pictureBig;
    }

    public void setPictureBig(String pictureBig) {
        this.pictureBig = pictureBig;
    }

    public String getPictureXl() {
        return pictureXl;
    }

    public void setPictureXl(String pictureXl) {
        this.pictureXl = pictureXl;
    }

    public Boolean getRadio() {
        return radio;
    }

    public void setRadio(Boolean radio) {
        this.radio = radio;
    }

    public String getTracklist() {
        return tracklist;
    }

    public void setTracklist(String tracklist) {
        this.tracklist = tracklist;
    }

    public Integer getPosition() {
        return position;
    }

    public void setPosition(Integer position) {
        this.position = position;
    }

    @Override
    public boolean isItemPlaying() {
        return getId() == getArtistPlayedId().longValue() && getPlayingType() == PlayingType.Artist && getState() == PlayingState.Playing;
    }
}

public abstract class PlayEntity extends PlayerStateEntity {

  public abstract boolean isItemPlaying();
}

public class ArtistsRepository {
    private final ChartArtistDao chartArtistDao;
    private final DeezerService deezerService;


    @Inject
    public ArtistsRepository(ChartArtistDao chartArtistDao, DeezerService deezerService) {
        this.chartArtistDao = chartArtistDao;
        this.deezerService = deezerService;
    }


    public LiveData<PagedList<ChartArtistDao.Artist>> getArtist() {



        return new PagedNetworkBoundResource<ChartArtistDao.Artist, ModelList<ChartArtistEntity>>() {

            @Override
            protected void saveCallResult(@NonNull ModelList<ChartArtistEntity> item) {
                if (item != null) {
                    chartArtistDao.saveArtists(item.getItems());
                }
            }

            @Override
            protected List<ChartArtistDao.Artist> loadFromDb(int startPosition, int count) {
                return chartArtistDao.loadArtists(startPosition, count);
            }

            @Override
            protected Call<ModelList<ChartArtistEntity>> createCall(int startPosition, int count) {
                return deezerService.getChartArtist(startPosition, count);
            }

        }.getAsLiveData();
    }
}

对于每个Artist项,我从PlayerStateEntity添加字段(不是很好的解决方案,但这是表示ui项状态的简单方法)。在PlayerStateEntity表更新后,Room应该通知数据更改,但是没有。

据我所知,Room不知道查询我使用的内容,也无法更新我的RecyclerView,它是通过分页库提供的。但也许有人知道如何通知Room我在我的DataSource中使用的表格以便将来触发ui更新?

1 个答案:

答案 0 :(得分:0)

问题与自定义DataSource实现有关。当数据发生变化时,LivePagedListProvider应为正确的ui更新创建一个新的DataSource实例。我使用了相同的实例,所以我以前的解决方案不对。