Я пытался внедрить бесконечную прокрутку в режиме рециркуляции.Я получил данные из комнаты, используя классы DAO и PostionalDatasourse.Но я не мог сделать бесконечную прокрутку.Было бы здорово, если бы кто-нибудь помог мне разобраться с этим. Возможно ли реализовать бесконечную прокрутку в представлении переработчика с использованием DAO, Liveata?Я знаю, что это возможно реализовать, если данные поступают с веб-сервера.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public RecyclerView recyclerView;
ProgressBar progressBar;
private GridLayoutManager gridLayoutManager;
private MyAdapter myAdapter;
int x = 10;//x = Numbers of max rows which will be cached whenscrolling.
int numberOfColumns = 1;
private boolean isScrolling = false;
private int firstScrolledItem, visibleItem, totalItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
progressBar = findViewById(R.id.progressBar);
//Attach the myAdapter to recyclerview
gridLayoutManager = new GridLayoutManager(this.getApplicationContext(), numberOfColumns);
gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(gridLayoutManager);
//setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height.
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(x);
myAdapter = new MyAdapter();
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.getLivePagedListData().observe(this, new Observer<PagedList<Item>>() {
@Override
public void onChanged(@Nullable PagedList<Item> liveObservedItem) {
loadData(liveObservedItem);
}
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true;
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
firstScrolledItem = gridLayoutManager.findFirstVisibleItemPosition();
visibleItem = gridLayoutManager.getChildCount();
totalItem = gridLayoutManager.getItemCount();
if(isScrolling && (totalItem >= (firstScrolledItem+visibleItem))){
loadMoreData();
isScrolling = false;
}
}
});
}
private void loadMoreData() {
progressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed (new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE);
}
}, 3000);
}
private void loadData(PagedList<Item> liveObservedItem) {
myAdapter.submitList(liveObservedItem);
recyclerView.setAdapter(myAdapter);
}
}
MyDataSource.java
public class MyDatSource extends PositionalDataSource<Item> {
private static String TAG = "MyDatSource";
int COUNT = 100;
private List<Integer> listOfPosition = new ArrayList<>((Arrays.asList(4,7,10,90)));
private List<Item> createNewItemsMatchingRequestedSize(int startPosition, int pagecount) {
List<Item> newItems = new ArrayList<>();
// actual load code here
for (int i = 0; i < pagecount; i++) {
Item item = new Item("Item " + i + " " + "startPosition(" + startPosition + ")");
//listOfPosition.contains(startPosition + i) is boolean to check wheck it's true or not
if (listOfPosition.contains(startPosition + i)) {
Log.e(TAG, "listOfPosition to be preSelected " + listOfPosition);
item.setSelected(true);
item.setListofPreSelectedPosition(listOfPosition);
Log.e(TAG, "preSelected item is : " + item );
}
newItems.add(item);
}
return newItems;
}
@Override
public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Item> callback) {
// int totalCount = computeCount();
// int position = computeInitialLoadPosition(params, totalCount);
// int loadSize = computeInitialLoadSize(params, position, totalCount);
callback.onResult(createNewItemsMatchingRequestedSize(params.requestedStartPosition, params.pageSize), params.requestedStartPosition, COUNT);
}
@Override
public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<Item> callback) {
List<Item> newLoadedItems = createNewItemsMatchingRequestedSize(params.startPosition, params.loadSize);
Log.d(TAG, String.valueOf(newLoadedItems));
callback.onResult(newLoadedItems);
}
public void saveSelectedItemInList(int position) {
listOfPosition.add(position);
Log.d(TAG, "checkbox state(true/false) at position " + position + " has been updated in the list of MyDatSource");
Log.d(TAG, "Updated listOfPosition in MyDatSource " + listOfPosition);
}
}
MyViewModel.java
public class MyViewModel extends ViewModel {
private static final int INITIAL_Load_Size = 30;
private static final int PAGE_SIZE = 20;
private static final Boolean Enable_Place_holders = false;
private static final int PREFETCH_DISTANCE = 10;//the paged list will attempt to load 10 items in advance of data that's already been accessed.
private static final int INITIAL_LOAD_KEY = 0;
Executor backgroundThreadexecuter;
PagedList.BoundaryCallback<Item> boundaryCallback;
MyDatSource dataSource;
//LiveData:Data holder class that keeps a value(here Item) and allows this value to be observed
public LiveData<PagedList<Item>> livePagedListData;
public MyViewModel() {
//newFixedThreadPool:Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue
// If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.
backgroundThreadexecuter = Executors.newFixedThreadPool(5);
// progressBar.setProgressBarVisibile();
getpagedListLiveData();
}
private final DataSource.Factory<Integer, Item> dataSourceFactory =
new DataSource.Factory<Integer, Item>() {
@Override
public DataSource create() {
dataSource = new MyDatSource();
return dataSource;
}
};
private final PagedList.Config pagedListConfig =
new PagedList.Config.Builder()
.setPrefetchDistance(PREFETCH_DISTANCE)//Distance the PagedList should prefetch.If not set, defaults to page size.
.setInitialLoadSizeHint(INITIAL_Load_Size)//Defines how many items to load when first load occurs.
.setPageSize(PAGE_SIZE)//Defines the number of items loaded at once from the MyDatSource.
.setEnablePlaceholders(Enable_Place_holders)
.build();
private void getpagedListLiveData() {
//LivePagedListBuilder:Builder for LiveData<PagedList>
livePagedListData = new LivePagedListBuilder<>(dataSourceFactory, pagedListConfig)
//setBoundaryCallback:Sets a PagedList.BoundaryCallback on each PagedList created, typically used to load
// additional data from network when paging from local storage.
//Pass a BoundaryCallback to listen to when the PagedList runs out of data to load
.setBoundaryCallback(boundaryCallback)
.setFetchExecutor(backgroundThreadexecuter) //Sets backgroundThreadexecuter which will be used for background loading of pages.
.setInitialLoadKey(INITIAL_LOAD_KEY)//When a new PagedList/MyDatSource pair is created after the first, it acquires a load key from the previous generation so that data is loaded around the position already being observed.
.build();
}
//Expose data to observe by Activity and display on UI
public LiveData<PagedList<Item>> getLivePagedListData() {
return livePagedListData;
}
}
Item.java
public class Item {
private String value;
private boolean selected ;
private List<Integer> listOfPreSelectedPosition;
public Item(String value) {
this.value = value;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public final static DiffUtil.ItemCallback<Item> DIFF_CALLBACK = new DiffUtil.ItemCallback<Item>() {
@Override
public boolean areItemsTheSame(@NonNull Item oldItem, @NonNull Item newItem) {
return oldItem.value.equals(newItem.value);
}
@Override
public boolean areContentsTheSame(@NonNull Item oldItem, @NonNull Item newItem) {
return oldItem.equals(newItem);
}
};
@Override
public String toString() {
return value.toString();
}
public List<Integer> getListOfPreSelectedPosition() {
return listOfPreSelectedPosition;
}
public void setListofPreSelectedPosition(List<Integer> lpp) {
this.listOfPreSelectedPosition = lpp;
}
}
MyAdapter.java
public class MyAdapter extends PagedListAdapter<Item, MyAdapter.ViewHolder> {
private static String TAG = "MyAdapter";
private MyDatSource dataSource = new MyDatSource();
MyAdapter() {
super(Item.DIFF_CALLBACK);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new View
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
ViewHolder viewholder = new ViewHolder(layoutView);
//setOnCheckedChangeListener():Register a callback to be invoked when the checked state of this button changes.
//compoundButton:A button with two states, checked and unchecked. When the button is pressed or clicked, the state changes automatically.
viewholder.checkBox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
if (compoundButton.isPressed()) {
viewholder.checkBox.setChecked(isChecked);
dataSource.saveSelectedItemInList(viewholder.getAdapterPosition());
}
});
return viewholder;
}
//Data is bound to views
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.lineTextView.setText(String.valueOf(getItem(position)));
int preSelectedPosition=4; //Get this position from event of dataSource or Item ...
if(holder.getAdapterPosition()==preSelectedPosition)
{
holder.checkBox.setChecked(true);
}
else
{
holder.checkBox.setChecked(false);
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView lineTextView;
public CheckBox checkBox;
public ViewHolder(View layoutView) {
super(layoutView);
lineTextView = layoutView.findViewById(R.id.line);
checkBox = layoutView.findViewById(R.id.checkbox);
}
}
}