Skip to content

Instantly share code, notes, and snippets.

@jsaund
jsaund / AsyncDiffUtil.kt
Created November 7, 2018 08:25
Android RecyclerView example of creating an Async Diff Util with Coroutines
internal sealed class UpdateListOperation {
object Clear : UpdateListOperation()
data class Insert(val newList: List<*>) : UpdateListOperation()
}
private val updateActor = actor<UpdateListOperation>(UI, CONFLATED, parent = job) {
consumeEach {
if (!isActive) return@actor
@jsaund
jsaund / jagsaund.zsh-theme
Created October 7, 2017 18:24
My oh-my-zsh theme
PROMPT='%{$fg[cyan]%}%c%{$reset_color%} $(git_prompt_info)%{$fg_bold[grey]%}[%*]: %{$reset_color%}'
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}[%{$fg[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[red]%}●%{$fg_bold[blue]%}]"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[green]%}●%{$fg_bold[blue]%}]"
@jsaund
jsaund / snaphelper.kt
Created September 17, 2017 23:14
Creating and using SnapHelper with RecyclerView
class MyActivity : AppCompatActivity {
override fun onCreate(savedInstanceState: Bundle?) {
val recyclerView = findViewById(R.id.list) as RecyclerView
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = ExampleAdapter()
LinearSnapHelper().attachToRecyclerView(recyclerView) // Configures the snap helper and attaches itself to the recycler view -- now items will snap to the center
}
}
@jsaund
jsaund / snaphelpertip2.kt
Created September 17, 2017 23:11
SnapHelper tip: Limit the time a scroll takes
private const val MILLISECONDS_PER_INCH = 100
private const val MAX_SCROLL_ON_FLING_DURATION = 250 // ms
override fun createSnapScroller(layoutManager: LayoutManager?): LinearSmoothScroller? {
if (layoutManager !is ScrollVectorProvider) return null
return object : LinearSmoothScroller(context) {
override fun onTargetFound(targetView: View?, state: State?, action: Action?) {
if (targetView == null) return
val snapDistances = calculateDistanceToFinalSnap(layoutManager, targetView)
val dx = snapDistances[0]
@jsaund
jsaund / snaphelpertip1.kt
Created September 17, 2017 23:07
SnapHelper tip: limit the maximum fling distance
private var scroller: Scroller? = null
private val minX = -2000
private val maxX = 2000
private val minY = -2000
private val maxY = 2000
override fun attachToRecyclerView(recyclerView: RecyclerView?) {
scroller = Scroller(recyclerView?.context, DecelerateInterpolator())
super.attachToRecyclerView(recyclerView)
}
@jsaund
jsaund / RxUtils.java
Created July 13, 2017 00:15
A collection of RxUtils for Android
public class RxUtils {
private RxUtils() {
}
@NonNull
public static Func1<Observable<? extends Throwable>, Observable<?>> retryWithBackoff(
final int maxAttempts, final long initialDelay, final TimeUnit unit) {
return errors -> errors
.zipWith(Observable.range(1, maxAttempts), (error, attempt) -> {
if (!isRetryable(error)) {
@jsaund
jsaund / RxEndlessScroller.java
Last active July 13, 2017 00:08
RxJava Android and Infinite Scrolling
public class RxEndlessScroller {
interface OnLoadMoreListener {
void loadMore();
}
private static class EndlessScrollListener extends RecyclerView.OnScrollListener {
private final int visibleItemCountThreshold;
@Nullable private OnLoadMoreListener loadMoreListener;
@jsaund
jsaund / .gitignore
Last active July 14, 2017 04:21
Typical Empty Android Project Template
# Compiled source #
###################
*.class
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
@jsaund
jsaund / rx_search_result_improved.java
Created February 23, 2017 21:17
Demonstrates using onErrorResumeNext to prevent terminating the upstream sequence. Notice that the onErrorResumeNext is applied inside the switchMap rather than outside.
public Observable<SearchResult> search(@NotNull EditText searchView) {
return RxTextView.textChanges(searchView) // In production, share this text view observable, don't create a new one each time
.map(CharSequence::toString)
.debounce(500, TimeUnit.MILLISECONDS) // Avoid getting spammed with key stroke changes
.filter(s -> s.length() > 1) // Only interested in queries of length greater than 1
.observeOn(workerScheduler) // Next set of operations will be network so switch to an IO Scheduler (or worker)
.switchMap(query -> searchService.query(query) // Take the latest observable from upstream and unsubscribe from any previous subscriptions
.onErrorResumeNext(Observable.empty()); // <-- This fixes the problem since the error is not seen by the upstream observable
}
@jsaund
jsaund / rx_search_results.java
Created February 23, 2017 21:11
An example of using onErrorResumeNext to try to prevent the upstream from terminating when an error is received -- this doesn't work!
public Observable<SearchResult> search(@NotNull EditText searchView) {
return RxTextView.textChanges(searchView) // In production, share this text view observable, don't create a new one each time
.map(CharSequence::toString)
.debounce(500, TimeUnit.MILLISECONDS) // Avoid getting spammed with key stroke changes
.filter(s -> s.length() > 1) // Only interested in queries of length greater than 1
.observeOn(workerScheduler) // Next set of operations will be network so switch to an IO Scheduler (or worker)
.switchMap(query -> searchService.query(query)) // Take the latest observable from upstream and unsubscribe from any previous subscriptions
.onErrorResumeNext(Observable.empty()); // <-- This will terminate upstream (ie. we will stop receiving text view changes after an error!)
}