Skip to content

Commit

Permalink
Merge pull request #17 from MaximeJallu/refactor_factory_view_holder
Browse files Browse the repository at this point in the history
fix(communication): remove default methods
  • Loading branch information
MaximeJallu authored Oct 27, 2017
2 parents 7594811 + cdd504b commit 86890df
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 66 deletions.
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ minSdkVersion = 16

# Gradle
```
compile "com.github.maximejallu:adapters:1.9"
compile "com.github.maximejallu:adapters:1.1.2"
```

# RecyclerAdapter (Easy sample method)
Expand Down Expand Up @@ -59,6 +59,7 @@ public class CustomerViewHolder2 extends RecyclerViewHolder<Customer> {
}
}

//# Solution 1 : the object determines are own item view type
public class Customer implements IViewType {
public static final int TYPE_ON_LINE = 0; /*default*/
public static final int TYPE_STORE = 1;
Expand All @@ -71,12 +72,24 @@ public class Customer implements IViewType {
}
}

private RecyclerAdapter<Customer> mAdapter;
public class MyFragment extends Fragment {

public void onCreateView(){
private RecyclerAdapter<Customer> mAdapter;

mAdapter = new RecyclerAdapter(customerList, CustomerViewHolder1.class/*type par default*/);
mAdapter.putViewType(Customer.TYPE_STORE, CustomerViewHolder2.class, null /*callback*/);
mAdapter.putViewType(Customer.TYPE_OTHER, CustomerViewHolder3.class, true /*add default callback*/);

//# Solution 2 : We give the strategy of the IViewType to our adapt it
mAdapter.setItemViewType(item -> {
//todo stategy type of item
return 0;
});
mRecyclerView.setAdapter(adapter);
}

mAdapter = new RecyclerAdapter(customerList, CustomerViewHolder1.class/*type par default*/);
mAdapter.putViewType(Customer.TYPE_STORE, CustomerViewHolder2.class);
mAdapter.putViewType(Customer.TYPE_OTHER, CustomerViewHolder3.class);
mRecyclerView.setAdapter(adapter);
}
```
# SectionDecorator (Recycler with LinearLayout)
precondition : create your RecyclerViewHolder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.android.jmaxime.factory.ViewHolderFactory;
import com.android.jmaxime.interfaces.IAdapterChanged;
import com.android.jmaxime.interfaces.IBaseCommunication;
import com.android.jmaxime.interfaces.IItemViewType;
import com.android.jmaxime.interfaces.IViewType;
import com.android.jmaxime.interfaces.InitViewHolderDecorator;
import com.android.jmaxime.interfaces.ShowPictureDecorator;
Expand All @@ -20,7 +21,8 @@
public class RecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder<T>> {

private List<T> mTList;
private ViewHolderFactory<T> mFactory;
private ViewHolderFactory<T> mViewHolderFactory;
private IItemViewType<T> mViewTypeStategy;
private IAdapterChanged mAdapterChanged;

public RecyclerAdapter() {
Expand Down Expand Up @@ -50,20 +52,20 @@ public RecyclerAdapter(List<T> TList, Class<? extends RecyclerViewHolder<T>> vie

public RecyclerAdapter(List<T> TList, ViewHolderFactory<T> factory) {
mTList = TList;
mFactory = factory;
mViewHolderFactory = factory;
}

public void setFactory(ViewHolderFactory<T> factory) {
mFactory = factory;
mViewHolderFactory = factory;
}

@Override
public RecyclerViewHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) {
if (mFactory == null) {
throw new AccessControlException("mFactory is not instancied. thanks use setFactory() method.");
if (mViewHolderFactory == null) {
throw new AccessControlException("mViewHolderFactory is not instancied. thanks use setFactory() method.");
}

RecyclerViewHolder<T> vh = mFactory.createVH(parent, viewType);
RecyclerViewHolder<T> vh = mViewHolderFactory.createVH(parent, viewType);
/*used for decorator. Sample ButterKnife*/
vh.initBinding();
return vh;
Expand Down Expand Up @@ -95,14 +97,24 @@ public T getItem(int position) {

@Override
public int getItemViewType(int position) {
if (getItem(position) != null && getItem(position) instanceof IViewType) {
if (mViewTypeStategy != null){
return mViewTypeStategy.getItemViewType(getItem(position));
}else if (getItem(position) != null && getItem(position) instanceof IViewType) {
return ((IViewType) getItem(position)).getItemViewType();
}
return super.getItemViewType(position);
}

public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder){
mFactory.putViewType(viewType, viewHolder);
public void setViewTypeFactory(IItemViewType<T> viewTypeStategy) {
mViewTypeStategy = viewTypeStategy;
}

public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder, boolean setDefaultCom){
mViewHolderFactory.putViewType(viewType, viewHolder, setDefaultCom);
}

public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder, IBaseCommunication callback){
mViewHolderFactory.putViewType(viewType, viewHolder, callback);
}

public boolean contains(final T obj) {
Expand All @@ -120,16 +132,16 @@ public void setOnAdapterChangedListener(IAdapterChanged adapterChanged) {
}

public void setCommunication(IBaseCommunication communication) {
mFactory.setCommunication(communication);
mViewHolderFactory.setCommunication(communication);
notifyDataSetChanged();
}

public void attachInitHolderDecorator(InitViewHolderDecorator holderDecorator) {
mFactory.setInitViewDecorator(holderDecorator);
mViewHolderFactory.setInitViewDecorator(holderDecorator);
}

public void attachShowPictureDecorator(ShowPictureDecorator pictureDecorator) {
mFactory.setShowPictureDecorator(pictureDecorator);
mViewHolderFactory.setShowPictureDecorator(pictureDecorator);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
public class ViewHolderFactory<T> {

private static final String TAG = ViewHolderFactory.class.getName();
private WeakReference<IBaseCommunication> mCommunication;
private static final int DEFAULT_VIEW_TYPE = 0;

private WeakReference<ShowPictureDecorator> mDecoratorWeakReference;
private WeakReference<InitViewHolderDecorator> mInitViewDecoratorWeakReference;
private Class<? extends RecyclerViewHolder<T>> mViewHolderType;
private SparseArray<Class<? extends RecyclerViewHolder<T>>> mClassHashMap;
private SparseArray<ViewTypeContainer<T>> mViewHashMap;

public ViewHolderFactory() {
this(null, null);
Expand All @@ -42,25 +42,27 @@ public ViewHolderFactory(Class<? extends RecyclerViewHolder<T>> viewHolderType)
this(viewHolderType, null);
}

public ViewHolderFactory(Class<? extends RecyclerViewHolder<T>> viewHolderType, @Nullable IBaseCommunication callback) {
public ViewHolderFactory(Class<? extends RecyclerViewHolder<T>> viewHolderType,
@Nullable IBaseCommunication callback) {
this(viewHolderType, callback, null, null);
}

public ViewHolderFactory(Class<? extends RecyclerViewHolder<T>> viewHolderType,
@Nullable IBaseCommunication callback, @Nullable InitViewHolderDecorator holderDecorator,
@Nullable ShowPictureDecorator pictureDecorator) {
mViewHolderType = viewHolderType;
mClassHashMap = new SparseArray<>();
setCommunication(callback);
@Nullable IBaseCommunication callback,
@Nullable InitViewHolderDecorator holderDecorator,
@Nullable ShowPictureDecorator pictureDecorator) {
mViewHashMap = new SparseArray<>();

mViewHashMap.put(DEFAULT_VIEW_TYPE, new ViewTypeContainer<>(viewHolderType, callback));
setInitViewDecorator(holderDecorator);
setShowPictureDecorator(pictureDecorator);
}

public final RecyclerViewHolder<T> createVH(ViewGroup view, int viewType) {
RecyclerViewHolder<T> ret = getInstance(LayoutInflater.from(view.getContext())
.inflate(getLayoutRes(viewType), view, false), viewType);
.inflate(getLayoutRes(viewType), view, false), viewType);
if (ret != null) {
ret.setCommunication(getInterfaceCallback());
ret.setCommunication(getInterfaceCallback(viewType));
ret.setInitViewDecorator(mInitViewDecoratorWeakReference.get());
ret.setPictureDecorator(mDecoratorWeakReference.get());
}
Expand All @@ -87,31 +89,31 @@ private RecyclerViewHolder<T> getInstance(View view, int viewType) {
return ret;
}

protected <I extends IBaseCommunication> I getInterfaceCallback() {
protected <I extends IBaseCommunication> I getInterfaceCallback(int viewType) {
I i = null;
try {
//noinspection unchecked
i = (I) getCommunication();
i = (I) getCommunication(viewType);
} catch (ClassCastException e) {
Log.e(TAG, "getInterfaceCallback: ", e);
}
return i;
}

protected Class<? extends RecyclerViewHolder<T>> getViewHolderType(int viewType) {
Class<? extends RecyclerViewHolder<T>> vm = mViewHolderType;
if (mClassHashMap.indexOfKey(viewType) > -1) {
vm = mClassHashMap.get(viewType);
Class<? extends RecyclerViewHolder<T>> vm = mViewHashMap.get(DEFAULT_VIEW_TYPE).mViewHolderType;
if (containsViewType(viewType)) {
vm = mViewHashMap.get(viewType).mViewHolderType;
}
return vm;
}

public final IBaseCommunication getCommunication() {
return mCommunication.get();
public final IBaseCommunication getCommunication(int viewType) {
return containsViewType(viewType) ? mViewHashMap.get(viewType).mCallback : null;
}

public void setCommunication(IBaseCommunication communication) {
mCommunication = new WeakReference<>(communication);
mViewHashMap.get(DEFAULT_VIEW_TYPE).mCallback = communication;
}

public void setShowPictureDecorator(@Nullable ShowPictureDecorator decoratorWeakReference) {
Expand All @@ -123,10 +125,54 @@ public void setInitViewDecorator(@Nullable InitViewHolderDecorator initViewDecor
}

final @LayoutRes int getLayoutRes(int viewType) {
return getViewHolderType(viewType).getAnnotation(BindLayoutRes.class).value();
return containsViewType(viewType) ? mViewHashMap.get(viewType).mLayoutResId : 0;
}

public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder, boolean setDefaultCommunication){
putViewType(viewType, viewHolder, setDefaultCommunication ? mViewHashMap.get(DEFAULT_VIEW_TYPE).mCallback : null);
}

public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder) {
mClassHashMap.put(viewType, viewHolder);
public void putViewType(int viewType, Class<? extends RecyclerViewHolder<T>> viewHolder, IBaseCommunication communicationCallback) {
if (viewType == 0){
throw new IllegalArgumentException("viewType must be greater than 0. Because 0 is reserved for viewHolder by default");
}
if (containsViewType(viewType)){
mViewHashMap.get(viewType).update(viewHolder, communicationCallback);
}else {
mViewHashMap.put(viewType, new ViewTypeContainer<>(viewHolder, communicationCallback));
}
}

private boolean containsViewType(int viewType){
return mViewHashMap.indexOfKey(viewType) > 0;
}

private static class ViewTypeContainer<T> {
Class<? extends RecyclerViewHolder<T>> mViewHolderType;
@LayoutRes int mLayoutResId;
IBaseCommunication mCallback;

public ViewTypeContainer(Class<? extends RecyclerViewHolder<T>> viewHolderType, IBaseCommunication callback) {
update(viewHolderType, callback);
}

public void update(Class<? extends RecyclerViewHolder<T>> viewHolderType, IBaseCommunication callback){
mViewHolderType = viewHolderType;
/*optimisation reflexion*/
mLayoutResId = getLayoutResId(viewHolderType);
mCallback = callback;
}

private int getLayoutResId(Class<? extends RecyclerViewHolder<T>> aClass){
checkViewType(aClass);
return aClass.getAnnotation(BindLayoutRes.class).value();
}

private void checkViewType(Class<? extends RecyclerViewHolder<T>> viewHolder) {
if (!viewHolder.isAnnotationPresent(BindLayoutRes.class)) {
throw new IllegalArgumentException(viewHolder.getSimpleName()
+ "is not annoted by " + BindLayoutRes.class.getSimpleName());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.android.jmaxime.interfaces;

public interface IItemViewType<T> {
int getItemViewType(T item);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package com.android.jmaxime.interfaces;

/**
* @author Maxime Jallu
* @since 29/09/2017
* <p>
* Use this Class for : <br/>
* {DOCUMENTATION}
*/
public interface IViewType {
int getItemViewType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
import com.android.jmaxime.adapters.decorators.CheckableAdapterDecorator;


/**
* @author Maxime Jallu
* @since 02/10/2017
* <p>
* Use this Class for : <br/>
* {DOCUMENTATION}
*/
public abstract class CheckableRecyclerViewHolder<T> extends RecyclerViewHolder<T> {

private boolean mIsChecked;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.android.jmaxime.viewholder;


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorRes;
Expand Down Expand Up @@ -43,15 +42,6 @@ public abstract class RecyclerViewHolder<T> extends RecyclerView.ViewHolder {
private ShowPictureDecorator mPictureDecorator;
private IBaseCommunication mCommunication;

/**
* This super() auto BindViews with ButterKnife<br/>
* <code>
* ButterKnife.bind(this, itemView);
* </code>
*
* @param itemView the Views holder
*/
@SuppressLint("NewApi")
public RecyclerViewHolder(View itemView) {
super(itemView);
}
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ ext {
buildToolsVersion = "26.0.1"
minSdkVersion = 16
targetSdkVersion = 26
versionCode = 1711122100
versionName = "1.9"
versionCode = 1711122210
versionName = "1.1.2"
}

task clean(type: Delete) {
Expand Down

0 comments on commit 86890df

Please sign in to comment.