Бесконечная прокрутка в виде переработчика с компонентами архитектуры Android - PullRequest
0 голосов
/ 05 октября 2018

Я пытался внедрить бесконечную прокрутку в режиме рециркуляции.Я получил данные из комнаты, используя классы 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);
        }
    }
}
...