Skip to content

Commit

Permalink
added first version of paging
Browse files Browse the repository at this point in the history
  • Loading branch information
skiff2011 committed Jan 29, 2020
1 parent 8ae5092 commit 2a4637c
Show file tree
Hide file tree
Showing 13 changed files with 327 additions and 27 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ buildscript {
minVersion = 14
gradlePluginVersion = '3.5.0'
kotlinVersion = '1.3.31'
coroutine_version = '1.3.0-RC2'
materialVersion = '1.0.0'
versionerVersion = '0.4.1'
lifecycle_version = '2.2.0-alpha04'
jUnitVersion = '4.12'
jUnitTestExtVersion = '1.1.1'
espressoVersion = '3.2.0'
Expand Down
9 changes: 8 additions & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ android {
minSdkVersion minVersion
targetSdkVersion targetVersion
versionCode gitVersioner.versionCode
versionName "2.0.1"
versionName "2.1.0"
println('VERSION_CODE: ' + gitVersioner.versionCode)

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand All @@ -33,6 +33,13 @@ dependencies {

implementation "androidx.recyclerview:recyclerview:$materialVersion"

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"

//lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

testImplementation "junit:junit:$jUnitVersion"
androidTestImplementation "androidx.test.ext:junit:$jUnitTestExtVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
Expand Down
147 changes: 147 additions & 0 deletions library/src/main/java/dev/auxility/baseadapter/EndlessAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package dev.auxility.baseadapter;

import androidx.annotation.NonNull;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import dev.auxility.baseadapter.item.Item;
import dev.auxility.baseadapter.misc.function.Predicate;

public class EndlessAdapter<V extends Item> extends AbstractAdapterDecorator<V> {

private final int threshold;
private final OnLoadMoreListener listener;
private boolean inProgress = false;
private boolean complete = false;

public EndlessAdapter(
@NonNull AbstractAdapter<V> decoratedAdapter,
int threshold,
OnLoadMoreListener listener
) {
super(decoratedAdapter);
this.threshold = threshold;
this.listener = listener;
}

public EndlessAdapter(int threshold, OnLoadMoreListener listener) {
this(new BaseAdapter<V>(), threshold, listener);
}

@Override
public int getSize() {
int size = getAdapter().getSize();
if (size == 0) {
checkThreshold(0);
}
return size;
}

@NonNull
@Override
public ListIterator<V> listIterator(int index) {
return getAdapter().listIterator(index);
}

@NonNull
@Override
public V get(int index) {
checkThreshold(index);
return getAdapter().get(index);
}

@NonNull
@Override
public List<V> items() {
return getAdapter().items();
}

@NonNull
@Override
public V remove(int index) {
return getAdapter().remove(index);
}

@Override
public boolean removeIf(@NonNull Predicate<V> predicate, boolean withDiffUtil) {
return getAdapter().removeIf(predicate, withDiffUtil);
}

@Override
public List<V> removeRange(int beginIndex, int endIndex) {
return getAdapter().removeRange(beginIndex, endIndex);
}

@Override
public void clear(boolean withDiffUtil) {
getAdapter().clear();
}

@Override
public void add(int index, @NonNull V element) {
getAdapter().add(index, element);
}

@Override
public boolean addAll(int index, @NonNull Collection<? extends V> c) {
return getAdapter().addAll(index, c);
}

@NonNull
@Override
public V set(int index, @NonNull V element) {
return getAdapter().set(index, element);
}

@Override
public void set(@NonNull Collection<? extends V> c, boolean withDiffUtil) {
getAdapter().set(c, withDiffUtil);
}

@NonNull
@Override
public Iterator<V> iterator() {
return getAdapter().iterator();
}

public int getThreshold() {
return threshold;
}

public boolean isInProgress() {
return inProgress;
}

public void setInProgress(boolean inProgress) {
this.inProgress = inProgress;
}

public boolean isComplete() {
return complete;
}

public void setComplete(boolean complete) {
this.complete = complete;
}

@Override
public void refresh() {
getAdapter().refresh();
}

private void checkThreshold(int index) {
if (!isComplete() && !isInProgress() && index >= getAdapter().getSize() - threshold) {
listener.onLoadMore(getAdapter().getSize());
}
}

public interface OnLoadMoreListener extends Serializable {

void onLoadMore(int currentSize);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.auxility.baseadapter.sample

import androidx.lifecycle.ViewModelProviders

class EndlessAdapterSampleFragment : TabbedFragment() {
override val titleRes: Int = R.string.endless_adapter_sample

override val viewModel: TabbedViewModel by lazy {
ViewModelProviders.of(this)
.get(EndlessAdapterViewModel::class.java)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.auxility.baseadapter.sample

import androidx.lifecycle.viewModelScope
import dev.auxility.baseadapter.Adapter
import dev.auxility.baseadapter.BaseAdapter
import dev.auxility.baseadapter.item.TitledItem

class EndlessAdapterViewModel : TabbedViewModel() {

override val adapter: Adapter<TitledItem> = BaseAdapter(
listOf(EndlessRVItem(viewModelScope))
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.auxility.baseadapter.sample

import android.util.Log
import dev.auxility.baseadapter.EndlessAdapter
import dev.auxility.baseadapter.item.Item
import dev.auxility.baseadapter.item.TitledItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

const val THRESHOLD = 10
const val PAGE_SIZE = 20
const val TOTAL_COUNT = 100

class EndlessRVItem(private val scope: CoroutineScope) : TitledItem, EndlessAdapter.OnLoadMoreListener {

val adapter: EndlessAdapter<Item> = EndlessAdapter(THRESHOLD, this)

override fun onLoadMore(currentSize: Int) {
Log.d("mytag", "loading $PAGE_SIZE items starting at $currentSize from $TOTAL_COUNT")
if (currentSize < TOTAL_COUNT) {
adapter.isInProgress = true
scope.launch {
adapter.add(ProgressItem())
delay(2000)
adapter.remove(adapter.size - 1)
adapter.addAll(List(PAGE_SIZE) {
TestItem(currentSize + it)
})
adapter.isInProgress = false
}
} else {
adapter.isComplete = true
}
}

override fun getLayoutId(): Int = R.layout.item_endless_rv

override fun getTitle(): String = "RecyclerView"
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,34 @@ import dev.auxility.baseadapter.sample.databinding.FragmentMainBinding

class MainFragment : androidx.fragment.app.Fragment() {

private lateinit var binding: FragmentMainBinding
private lateinit var binding: FragmentMainBinding

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(
inflater,
layout.fragment_main, container, false
)
binding.baseAdapterBtn.setOnClickListener { btn ->
btn.findNavController()
.navigate(
R.id.action_mainFragment_to_baseAdapterSampleFragment
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(
inflater,
layout.fragment_main, container, false
)
binding.baseAdapterBtn.setOnClickListener { btn ->
btn.findNavController()
.navigate(
R.id.action_mainFragment_to_baseAdapterSampleFragment
)
}
binding.filterableAdapterBtn.setOnClickListener { btn ->
btn.findNavController()
.navigate(
R.id.action_mainFragment_to_filterableAdapterSampleFragment
)
}
binding.endlessAdapterBtn.setOnClickListener {
it.findNavController().navigate(
R.id.action_mainFragment_to_endlessAdapterSampleFragment
)
}
return binding.root
}
binding.filterableAdapterBtn.setOnClickListener { btn ->
btn.findNavController()
.navigate(
R.id.action_mainFragment_to_filterableAdapterSampleFragment
)
}
return binding.root
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.auxility.baseadapter.sample

import dev.auxility.baseadapter.item.Item

class ProgressItem : Item {
override fun getLayoutId(): Int = R.layout.item_progress
}
18 changes: 15 additions & 3 deletions sample/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,25 @@
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/filterableadapter_sample"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/endlessAdapterBtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/baseAdapterBtn"
app:layout_constraintWidth_percent="0.7"
/>
app:layout_constraintWidth_percent="0.7" />

<Button
android:id="@+id/endlessAdapterBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/endless_adapter_sample"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/filterableAdapterBtn"
app:layout_constraintWidth_percent="0.7" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
21 changes: 21 additions & 0 deletions sample/src/main/res/layout/item_endless_rv.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="item"
type="dev.auxility.baseadapter.sample.EndlessRVItem" />
</data>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
adapter="@{item.adapter}"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_rv_sample" />

</layout>
Loading

0 comments on commit 2a4637c

Please sign in to comment.