Skip to content

Commit

Permalink
Merge branch 'release/1.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
paribeiro10 committed Oct 3, 2017
2 parents fdd30ed + e60acab commit 3acdb01
Show file tree
Hide file tree
Showing 30 changed files with 927 additions and 247 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Configuration
```gradle
dependencies {
...
compile 'pt.simdea:gmlrva.lib:1.2'
compile 'pt.simdea:gmlrva.lib:1.3'
...
}
```
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {

dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'pt.simdea.verifier:verifier:3.5.7SNAP3'
classpath 'pt.simdea.verifier:verifier:3.5.8'
classpath 'com.novoda:bintray-release:0.5.0'

// NOTE: Do not place your application dependencies here; they belong
Expand Down
3 changes: 2 additions & 1 deletion gmlrva-lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ android {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}

}

dependencies {
Expand All @@ -63,7 +64,7 @@ project.ext {
description = 'Generic RecyclerView Adapter that supports multiple layouts.'
groupId = 'pt.simdea'
artifactId = 'gmlrva.lib'
version = "1.2"
version = "1.3"
website = 'https://github.com/simdea/gmlrva'
scm = 'https://github.com/simdea/gmlrva'
tags = ['android', 'recyclerview', 'adapter', 'generic', 'multiple', 'layout']
Expand Down
6 changes: 4 additions & 2 deletions gmlrva-lib/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="pt.simdea.gmlrva.lib">

<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"/>
android:label="@string/gmlrva_app_name"
android:supportsRtl="true"
tools:replace="android:label"/>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@

package pt.simdea.gmlrva.lib;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

import lombok.AllArgsConstructor;

import static pt.simdea.gmlrva.lib.GenericPayload.UPDATE_ITEM;

/**
* Generic {@link RecyclerView.Adapter} base class reponsible for binding "all intents and purposes" layout
* Generic {@link RecyclerView.Adapter} base class responsible for binding "all intents and purposes" layout
* implementations applied to {@link RecyclerView} instances.
*
* @param <T> Generic Layout Implementation to be handled by this adapter.
Expand All @@ -22,22 +27,29 @@
* Simdea © All Rights Reserved.
* [email protected]
*/
@SuppressWarnings("unused")
@AllArgsConstructor
public class GenericMultipleLayoutAdapter<T extends GenericRecyclerViewLayout>
@SuppressWarnings({"unused", "unchecked"})
@AllArgsConstructor public class GenericMultipleLayoutAdapter<T extends GenericRecyclerViewLayout>
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private final List<T> mDataSet;
private List<T> mDataSet = new ArrayList<>();

@Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
return mDataSet.get(viewType).createViewHolder(parent);
}

@SuppressWarnings("unchecked") @Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder,
final int position) {
@Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
mDataSet.get(position).setElements(holder);
}

@Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position,
@NonNull final List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
applyPayloads(payloads, position);
}
}

@Override public int getItemCount() {
return mDataSet.size();
}
Expand All @@ -47,103 +59,44 @@ public class GenericMultipleLayoutAdapter<T extends GenericRecyclerViewLayout>
}

/**
* Procedure meant to insert a Generic Layout Implementation item on this adapter's data set.
* @param item a Generic Layout Implementation item.
*/
public void add(@NonNull final T item) {
final int index = validateItemPosition(item);
mDataSet.add(item);
notifyItemInserted(index);
}

/**
* Procedure meant to insert a list of Generic Layout Implementation item on this adapter's data set.
* @param items the list of Generic Layout Implementation items to be inserted.
*/
public void add(@NonNull final List<T> items) {
final int index = validateLastItemPosition();
mDataSet.addAll(items);
notifyItemRangeChanged(index, items.size());
}

/**
* Procedure meant to insert a Generic Layout Implementation item on this adapter's data set, at a target position.
* @param item a Generic Layout Implementation item.
* @param position the target position for this item to be inserted.
* @throws IndexOutOfBoundsException if the position is out of range
* (<tt>position &lt; 0 || position &gt; size()</tt>)
*/
public void add(@NonNull final T item, final int position) {
mDataSet.add(position, item);
notifyItemChanged(position);
}

/**
* Procedure meant to remove a Generic Layout Implementation item on this adapter's data set, at a target position.
* @param position the target position for this item to be removed.
* Procedure meant to update this adapter's entire data set.
* This procedure checks for the changes made to this adapter's data set and applies these changes exclusively,
* meaning there are no wasted operations.
* @param items the list of Generic Layout Implementation items for the data set.
*/
public void remove(final int position) {
if (!mDataSet.isEmpty() && validateItemPosition(position)) {
mDataSet.remove(position);
notifyItemRemoved(position);
}
public void updateList(@NonNull final List<T> items) {
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new GmlrvaDiffCallback<>(this.mDataSet, items));
mDataSet = items;
diffResult.dispatchUpdatesTo(this);
}

/**
* Procedure meant to remove a list of Generic Layout Implementation item on this adapter's data set.
* @param items the list of Generic Layout Implementation items to be removed.
* Procedure meant to apply a given payload to this adapter's data set.
* @param payloads the payload bundle object with the updates.
* @param position the adapter's position to be updated.
*/
public void remove(@NonNull final List<T> items) {
if (!mDataSet.isEmpty() && !items.isEmpty()) {
final int index = validateLastItemPosition();
mDataSet.removeAll(items);
notifyItemRangeRemoved(index, items.size());
private void applyPayloads(@NonNull final List<Object> payloads, final int position) {
final Bundle payload = (Bundle) payloads.get(0);
if (payload != null && payload.keySet() != null) {
for (final String key : payload.keySet()) {
if (UPDATE_ITEM.equals(key)) {
applyPayloadChange(position, payload, key);
}
}
}
}

/**
* Procedure meant to update a Generic Layout Implementation item present on this adapter's data set.
* @param item a Generic Layout Implementation item.
*/
public void update(@NonNull final T item) {
add(item);
}

/**
* Procedure meant to swap this adapter's entire data set.
* @param items the list of Generic Layout Implementation items to be added.
* Procedure meant to apply a given {@link RecyclerView.ViewHolder} change on this adapter's data set.
* @param position the adapter's position to be updated.
* @param payload the payload bundle object with the updates.
* @param key the payload key for the update value object.
*/
public void swap(@NonNull final List<T> items) {
if (!items.isEmpty()) {
mDataSet.clear();
mDataSet.addAll(items);
notifyDataSetChanged();
private void applyPayloadChange(final int position, @NonNull final Bundle payload, @NonNull final String key) {
final RecyclerView.ViewHolder newHolder = (RecyclerView.ViewHolder) payload.get(key);
if (newHolder != null) {
mDataSet.get(position).setElements(newHolder);
}
}

/**
* Procedure meant to perform an integrity check on a target index.
* @param index the target index.
* @return whether the target index is in range on this adapter's data set.
*/
private boolean validateItemPosition(final int index) {
return index > 0 && index < getItemCount();
}

/**
* Procedure meant to check the position of a target item on the data set.
* @param item the target Generic Layout Implementation item.
* @return the position of a target item on the data set if it exists, else returns the next position to be filled.
*/
private int validateItemPosition(@NonNull final T item) {
return mDataSet.contains(item) ? mDataSet.indexOf(item) : getItemCount();
}

/**
* Procedure meant to check the last known filled position on the data set.
* @return the last known filled position on the data set.
*/
private int validateLastItemPosition() {
return getItemCount() - 1 < 0 ? 0 : getItemCount() - 1;
}
}
33 changes: 33 additions & 0 deletions gmlrva-lib/src/main/java/pt/simdea/gmlrva/lib/GenericPayload.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2017. Simdea.
*/

package pt.simdea.gmlrva.lib;

import android.support.annotation.StringDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import lombok.AllArgsConstructor;

/**
* Magic Constant Annotation Enum containing the possible {@link GenericPayload} change key options.
*
* Created by Paulo Ribeiro on 9/26/2017.
* Simdea © All Rights Reserved.
* [email protected]
*/
@SuppressWarnings("WeakerAccess") @AllArgsConstructor public class GenericPayload {

/* Constants */

/** UPDATE_ITEM representing an item that needs to be updated. */
public static final String UPDATE_ITEM = "UPDATE_ITEM";

// Declare the @StringDef for these constants
@StringDef({ UPDATE_ITEM })
@Retention(RetentionPolicy.SOURCE)
public @interface GenericPayloadConstants { /* Do nothing here ... */ }

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import java.io.Serializable;

/**
* Interface meant to define a contract in which we specify the rules for building a Generic {@link RecyclerView} Layout
* (used for binding the data).
Expand All @@ -18,18 +20,26 @@
* Simdea © All Rights Reserved.
* [email protected]
*/
@SuppressWarnings("WeakerAccess") public interface GenericRecyclerViewLayout<T extends RecyclerView.ViewHolder> {
@SuppressWarnings("WeakerAccess")
public interface GenericRecyclerViewLayout<T extends RecyclerView.ViewHolder> extends Serializable {

/**
* Procedure meant to handle the ViewHolder instance creation.
* @param parent the root ViewGroup {@link ViewGroup} for the ViewHolder instance.
* @return the created ViewHolder instance.
*/
T createViewHolder(@NonNull final ViewGroup parent);
@NonNull T createViewHolder(@NonNull final ViewGroup parent);

/**
* Procedure meant to bind the target data from a model to the ViewHolder item {@link RecyclerView.ViewHolder}.
* @param holder the {@link RecyclerView.ViewHolder} instance.
*/
void setElements(@NonNull final T holder);

/**
* Procedure meant to define a tag for the ViewHolder item {@link RecyclerView.ViewHolder}.
* @return the {@link Object} representing the ViewHolder item {@link RecyclerView.ViewHolder}'s tag.
*/
@NonNull Object getTag();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2017. Simdea.
*/

package pt.simdea.gmlrva.lib;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;

import java.util.List;

import lombok.AllArgsConstructor;

import static pt.simdea.gmlrva.lib.GenericPayload.UPDATE_ITEM;

/**
* Generic {@link DiffUtil.Callback} base class responsible for parsing changes to the
* {@link GenericMultipleLayoutAdapter} implementation applied to {@link RecyclerView} instances.
*
* @param <T> an instance of {@link GenericRecyclerViewLayout}.
*
* Created by Paulo Ribeiro on 9/26/2017.
* Simdea © All Rights Reserved.
* [email protected]
*/
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@AllArgsConstructor class GmlrvaDiffCallback<T extends GenericRecyclerViewLayout> extends DiffUtil.Callback {

private final List<T> mOldList;
private final List<T> mNewList;

@Override public int getOldListSize() {
return mOldList.size();
}

@Override public int getNewListSize() {
return mNewList.size();
}

@Override public boolean areItemsTheSame(final int oldItemPosition, final int newItemPosition) {
return !mOldList.get(oldItemPosition).getTag().equals(mNewList.get(newItemPosition).getTag());
}

@Override public boolean areContentsTheSame(final int oldItemPosition, final int newItemPosition) {
return mOldList.get(oldItemPosition).getTag().equals(mNewList.get(newItemPosition).getTag());
}

@Nullable @Override public Object getChangePayload(final int oldItemPosition, final int newItemPosition) {
final T oldItem = mOldList.get(oldItemPosition);
final T newItem = mNewList.get(oldItemPosition);
final Bundle diffBundle = new Bundle();
if (!newItem.getTag().equals(oldItem.getTag())) {
diffBundle.putSerializable(UPDATE_ITEM, newItem);
}
if (diffBundle.size() == 0) {
return null;
}
return diffBundle;
}

}
Loading

0 comments on commit 3acdb01

Please sign in to comment.