Renderers is an Android library created to avoid all the boilerplate needed to use a RecyclerView/ListView with adapters.

Related tags

Adapter Renderers
Overview

Renderers Build Status Maven Central

Renderers is an Android library created to avoid all the RecyclerView/Adapter boilerplate needed to create a list/grid of data in your app and all the spaghetti code that developers used to create following the ViewHolder classic implementation. As performance is also important for us, we've added a new diffUpdate and a RVListRendererAdapter method supporting differential updated transparently in the main thread and a background thred respectively.

With this library you can improve your RecyclerView/Adapter/ViewHolder code. The one sometimes we copy and paste again and again 😃 . Using this library you won't need to create any new class extending from RecyclerViewAdapter.

Create your Renderer classes and declare the mapping between the object to render and the Renderer. The Renderer will use the model information to draw your user interface. You can reuse them in all your RecyclerView and ListView implementations easily. That's it!

Screenshots

Demo Screenshot

Usage

To use Renderers Android library you only have to follow three steps:

    1. Create your Renderer class or classes extending Renderer<T>. Inside your Renderer classes. You will have to implement some methods to inflate the layout you want to render and implement the rendering algorithm.
public class VideoRenderer extends Renderer<Video> {

       @BindView(R.id.iv_thumbnail)
       ImageView thumbnail;
       @BindView(R.id.tv_title)
       TextView title;
       @BindView(R.id.iv_marker)
       ImageView marker;
       @BindView(R.id.tv_label)
       TextView label;

       @Override
       protected View inflate(LayoutInflater inflater, ViewGroup parent) {
           View inflatedView = inflater.inflate(R.layout.video_renderer, parent, false);
           ButterKnife.bind(this, inflatedView);
           return inflatedView;
       }

       @Override
       protected void render() {
           Video video = getContent();
           renderThumbnail(video);
           renderTitle(video);
           renderMarker(video);
           renderLabel();
       }

       @OnClick(R.id.iv_thumbnail)
       void onVideoClicked() {
           Video video = getContent();
           Log.d("Renderer", "Clicked: " + video.getTitle());
       }

       private void renderThumbnail(Video video) {
           Picasso.with(context).load(video.getResourceThumbnail()).placeholder(R.drawable.placeholder).into(thumbnail);
       }

       private void renderTitle(Video video) {
           this.title.setText(video.getTitle());
       }
}

You can use Jake Wharton's Butterknife library to avoid findViewById calls inside your Renderers if you want. But the usage of third party libraries is not mandatory.

    1. If you have just one type of item in your list, instantiate a RendererBuilder with a Renderer instance and you are ready to go:
Renderer<Video> renderer = new LikeVideoRenderer();
RendererBuilder<Video> rendererBuilder = new RendererBuilder<Video>(renderer);

If you need to render different objects into your list/grid you can use RendererBuilder.bind fluent API and that's it:

RendererBuilder<Video> rendererBuilder = new RendererBuilder<Video>()
         .bind(VideoHeader.class, new VideoHeaderRenderer())
         .bind(Video.class, new LikeVideoRenderer());
    1. Initialize your ListView or RecyclerView with your RendererBuilder and your AdapteeCollection instances inside your Activity or Fragment. You can use ListAdapteeCollection or create your own implementation creating a class which implements AdapteeCollection to configure your RendererAdapter or RVRendererAdapter.
private void initListView() {
    adapter = new RendererAdapter<Video>(rendererBuilder, adapteeCollection);
    listView.setAdapter(adapter);
}

or

private void initListView() {
    adapter = new RVRendererAdapter<Video>(rendererBuilder, adapteeCollection);
    recyclerView.setAdapter(adapter);
}

Remember, if you are going to use RecyclerView instead of ListView you'll have to use RVRendererAdapter instead of RendererAdapter.

    1. Diff updates:

If the RecyclerView performance is crucial in your application remember you can use diffUpdate method in your RVRendererAdapter instance to update just the items changed in your adapter and not the whole list/grid.*

adapter.diffUpdate(newList)

This method provides a ready to use diff update for our adapter based on the implementation of the standard equals and hashCode methods from the Object Java class. The classes associated to your renderers will have to implement equals and hashCode methods properly. Your hashCode implementation can be based on the item ID if you have one. You can use your hashCode implementation as an identifier of the object you want to represent graphically. We know this implementation is not perfect, but is the best we can do wihtout adding a new interface you have to implement to the library breaking all your existing code. Here you can review the DiffUtil.Callback implementation used in this library. If you can't follow this implementation you can always use a different approach combined with your already implemented renderers.

Also, RVListRendererAdapter provides a way to perform diff updates in a background thread transparently. When using RVListRendererAdapter you'll have a default DiffUtil.ItemCallback implementation (https://developer.android.com/reference/android/support/v7/util/DiffUtil.ItemCallback)) based on referencial equality for areItemsTheSame method and structural equality for areContentsTheSame method. You also have constructors on this class to provide your own implementation for DiffUtil.ItemCallback. You can even configure the threads used to perform the calculations through AsynDifferConfig class (https://developer.android.com/reference/android/support/v7/recyclerview/extensions/AsyncDifferConfig).

This library can also be used to show views inside a ViewPager. Take a look at VPRendererAdapter 😃

Usage

Add this dependency to your build.gradle:

dependencies{
    implementation 'com.github.pedrovgs:renderers:4.0.0'
}

Complex binding

If your renderers binding is complex and it's not based on different classes but in properties of these classes, you can also extend RendererBuilder and override getPrototypeClass to customize your binding as follows:

public class VideoRendererBuilder extends RendererBuilder<Video> {

  public VideoRendererBuilder() {
    List<Renderer<Video>> prototypes = getVideoRendererPrototypes();
    setPrototypes(prototypes);
  }

  /**
   * Method to declare Video-VideoRenderer mapping.
   * Favorite videos will be rendered using FavoriteVideoRenderer.
   * Live videos will be rendered using LiveVideoRenderer.
   * Liked videos will be rendered using LikeVideoRenderer.
   *
   * @param content used to map object-renderers.
   * @return VideoRenderer subtype class.
   */
  @Override
  protected Class getPrototypeClass(Video content) {
    Class prototypeClass;
    if (content.isFavorite()) {
      prototypeClass = FavoriteVideoRenderer.class;
    } else if (content.isLive()) {
      prototypeClass = LiveVideoRenderer.class;
    } else {
      prototypeClass = LikeVideoRenderer.class;
    }
    return prototypeClass;
  }

  /**
   * Create a list of prototypes to configure RendererBuilder.
   * The list of Renderer<Video> that contains all the possible renderers that our RendererBuilder
   * is going to use.
   *
   * @return Renderer<Video> prototypes for RendererBuilder.
   */
  private List<Renderer<Video>> getVideoRendererPrototypes() {
    List<Renderer<Video>> prototypes = new LinkedList<Renderer<Video>>();
    LikeVideoRenderer likeVideoRenderer = new LikeVideoRenderer();
    prototypes.add(likeVideoRenderer);

    FavoriteVideoRenderer favoriteVideoRenderer = new FavoriteVideoRenderer();
    prototypes.add(favoriteVideoRenderer);

    LiveVideoRenderer liveVideoRenderer = new LiveVideoRenderer();
    prototypes.add(liveVideoRenderer);

    return prototypes;
  }
}

References

You can find implementation details in these talks:

Software Design Patterns on Android Video

Software Design Patterns on Android Slides

Developed By

Follow me on Twitter Add me to Linkedin

License

Copyright 2016 Pedro Vicente Gómez Sánchez

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Making use of Collection instead of AdapteeCollection

    Making use of Collection instead of AdapteeCollection

    Hi everyone!

    I would like to know if we could change RVRendererAdapter and RVListRendererAdapter collection type to Collection<T> instead of AdapteeCollection<T>.

    It causes me trouble in the following situation. I would like to update just one item from the list instead of performing a full diffUpdate. Since there is no set method in AdapteeCollection I can only do the following:

    List<T> list = (List<T>) collection;
    list.set(position, newElement);
    notifyItemChanged(position);
    

    The drawback of this approach is that it is performing a cast over collection assuming that the implementation inherits from List.

    Another way of tackling this issue would be copying all elements into aList<T> and performing the set operation there. But that is even worse given the original collection is already a List<T> and we would be doing a useless copy.

    Are there any arguments against using Collection instead of AdapteeCollection?

    opened by Lukard 7
  • FIX #24. Changed generics in interface of RendererBuilder.

    FIX #24. Changed generics in interface of RendererBuilder.

    Changed RendererBuilder generics for supporting descendants classes to FIX #24.

    E.g. In case when B, C extends A. This change allows to create RendererBuilder<A> And bind rendering C objects using Renderer<C> and B objects to render with Renderer<B>.

    Also this change improves encapsulation.

    Changed constructor to public RendererBuilder(Collection<? extends Renderer<? extends T>> prototypes) that allows to use descendants. e.g. When we have class A that extends B, we can use for creating RendererBuilder<B> collection that contains Renderer<A> and Renderer<B>. And bindings will configure what renderer should be used for what model class.

    Added copy of collection to constructor for better encapsulation.

    getPrototypes added Collections.unmodifiableList for better encapsulation.

    public final void setPrototypes(Collection<? extends Renderer<? extends T>> prototypes) and RendererBuilder<T> withPrototypes(Collection<? extends Renderer<? extends T>> prototypes) changed to received descendants renderers.

    opened by roshakorost 7
  • Make AdapteeCollection compatible with List interface,

    Make AdapteeCollection compatible with List interface,

    Make AdapteeCollection<T> compatible with List<T> interface, so any class implementing a List could be used as an AdapteeCollection by simply implementing it. For example, ListAdapteeCollection<T> can be now implemented with less code.

    opened by raycoarana 6
  • Ejemplo más sencillo

    Ejemplo más sencillo

    Puedes subir algún ejemplo un poco más sencillo y directo?

    Me está costando un poco implementar la librería en mi proyecto. Me he liado un poco con el ejemplo que tienes subido.

    Sobre todo a la hora de iniciar el adaptador:

    RendererAdapter adapter = new RendererAdapter(inflater,B, C);

    En B que incluyo? y en C?

    Gracias.

    opened by devloe 6
  • RVRendererAdapter.addAll doesn't respect Collection.addAll signature

    RVRendererAdapter.addAll doesn't respect Collection.addAll signature

    RVRendererAdapter addAll signature differs from the Collection one making it impossible to use it with collections of subtypes. The fix is as easy as changing the method signature from

    public void addAll(Collection<T> elements)
    

    to

    public void addAll(Collection<? extends T> elements)
    

    It will be backwards compatible which is always nice.

    enhancement 
    opened by Serchinastico 4
  • Update dependencies Issue#44

    Update dependencies Issue#44

    Hi @pedrovgs!

    As indicated in Issue#44, I updated the dependencies and adapted the code to the corresponding API changes.

    The only dependency which hasn't been updated to the latest version is ButterKnife. It was causing conflicts with androidX and it required minSdk Android N.

    I hope it this is useful! Cheers.

    This closes #44

    opened by marcbenedi 3
  • Add support for PagedListAdapter

    Add support for PagedListAdapter

    After the latest Architecture Components release made by Google during December 2017 we've noticed they have released a new adapter named PagedListAdapter we should support. As the architecture component is a new module we should provide this as a new renderers module so we don't add the architecture components to the main artifact. More information can be found in this video

    enhancement help wanted 
    opened by pedrovgs 3
  • Create DiffRVRendererAdapter to use RecyclerView's DiffUtil

    Create DiffRVRendererAdapter to use RecyclerView's DiffUtil

    Creates DiffRVRendererAdapter that extends RVRendererAdapter but provides and interface in order to work in combination with the new DiffUtil that comes with the support library.

    Also an example is provided.

    opened by FireZenk 3
  • Added Collection setter in RVRendererAdapter

    Added Collection setter in RVRendererAdapter

    In some occasions when it creates a AdapteeCollection for RVRendererAdapter needs a RecyclerView.Adapter.

    • Problem example using package android.support.v7.util.SortedList:
    public MyAdapteeCollectionConstructor(RecyclerView.Adapter ANY_ADAPTER) {
    
        this.messageList = new SortedList<Message>(Message.class, new SortedListAdapterCallback<Message>(ANY_ADAPTER) {
                @Override
                public int compare(Message o1, Message o2) {
                    return o1.compareTo(o2);
                }
    
                @Override
                public boolean areContentsTheSame(Message oldItem, Message newItem) {
                    return oldItem.equals(newItem);
                }
    
                @Override
                public boolean areItemsTheSame(Message item1, Message item2) {
                    return item1.getId().equals(item2.getId());
                }
            });
    }
    

    RVRendererAdapter creation:

    adapter = new RVRendererAdapter<Message>(new MessageRenderBuilder(), new MyAdapteeCollection(WHAT ADAPTER?));
    

    • Solution with actual Renderers version for this example:
    public MyAdapteeCollectionConstructor() {
        //init default messageList
    }
    
    ...
    
     public void initCollection(RecyclerView.Adapter adapter) {
            messageList = new SortedList<Message>(Message.class, new SortedListAdapterCallback<Message>(adapter) {
                @Override
                public int compare(Message o1, Message o2) {
                    return o1.compareTo(o2);
                }
    
                @Override
                public boolean areContentsTheSame(Message oldItem, Message newItem) {
                    return oldItem.equals(newItem);
                }
    
                @Override
                public boolean areItemsTheSame(Message item1, Message item2) {
                    return item1.getId().equals(item2.getId());
                }
            });
        }
    

    RVRendererAdapter creation:

    adapteeCollection = new MyAdapteeCollection();
    adapter = new RVRendererAdapter<Message>(new MessageRenderBuilder(), adapteeCollection);
    adapteeCollection.initCollection(adapter);
    

    • Solution with for this example (better solution?):
    public MyAdapteeCollectionConstructor(RecyclerView.Adapter ANY_ADAPTER) { ... }
    

    RVRendererAdapter creation:

    adapter = new RVRendererAdapter<Message>(new MessageRenderBuilder());
    adapter.setCollection(new MyAdapteeCollection(adapter));
    
    opened by tonilopezmr 3
  • Create Sample for new Generic Functionality

    Create Sample for new Generic Functionality

    Hello,

    I have started work on new sample, that binds different renderer classes to different model classes, was planing to make it on top of Video and VideoRenderer. But there are problems: VideoRenderer sets layout that will use in subclasses, Video model has too much fields.

    What if I would make completely different example, not about videos?

    enhancement 
    opened by roshakorost 3
  • Listener de click a elemento de la lista

    Listener de click a elemento de la lista

    Buenas Pedro, no consigo entender como implementar la gestion del click a un elemento de la lista sin hacer uso de inyeccion de dependencias..¿Tienes algun ejemplo? Gracias por la libreria, creo que me va a ahorrar años de dolores de cabeza xD

    opened by rfermontero 3
  • Improve Kotlin support

    Improve Kotlin support

    We are going to update all the project documentation and add a new module supporting Kotlin properly. We will make the library more idiomatic and kotlin friendly so our Android users can enjoy it 😃

    enhancement kotlin 
    opened by pedrovgs 1
  • Support for LayoutContainer

    Support for LayoutContainer

    As it turns out, Kotlin synthetic properties cache works by default on Activities, Fragments, and Views, but it does not do so for ViewHolder. They fixed this as of Kotlin 1.1.4 via LayoutContainer.

    Consumers of this libraries have to make sure they make their Renderers implement LayoutContainer if they are using synthetic properties inside of them. If they do not, their ViewHolders are going to call findViewById() on every call to render() making their ViewHolders obsolete. It would be nice if the library itself did this maybe by adding a Kotlin specific artifact that implements this interface (implementation should be trivial). Thoughts?

    enhancement help wanted 
    opened by emmano 11
Releases(4.1.0)
Owner
Pedro Vicente Gómez Sánchez
"Sometimes it is the people no one imagines anything of who do the things no one can imagine." - Alan Turing
Pedro Vicente Gómez Sánchez
[] Easy Adapters library for Android

Deprecated Due to the growing use of the RecyclerView and the RecyclerView.Adapter provided adapter class, Easy-Adapter is now deprecated. Whilst the

ribot 425 Nov 25, 2022
Adapter Kit is a set of useful adapters for Android.

Adapter Kit Adapter Kit is a set of useful adapters for Android. The kit currently includes, Instant Adapter Instant Cursor Adapter Simple Section Ada

Ragunath Jawahar 368 Nov 25, 2022
Generate data-view-binding adapters of android recycler view.

Items 这个库可以为 Android 的 RecyclerView 生成基于 Data-View-Binding 的 Adapter。 对比其他一些类似的开源库,它有以下的一些优势: 更好的拓展性。这个库不需要你继承特定的 Adapter 或 ViewHolder 类,你可以继承任何第三方提供的

nekocode 253 Nov 11, 2022
Just like instant coffee, saves 78% of your time on Android's Custom Adapters.

Notice Instant Adapter is now part of an even more awesome Adapter Kit project! Instant Adapter Just like instant coffee, saves 78%* of your time on A

Ragunath Jawahar 232 Nov 25, 2022
This library provides GridAdapters(ListGridAdapter & CursorGridAdapter) which enable you to bind your data in grid card fashion within android.widget.ListView, Also provides many other features related to GridListView.

GridListViewAdapters This libarary enables you to implement GridView like card layout within ListView with added capabilites like Paginations, Additio

Biraj Patel 270 Nov 25, 2022
Android - A ListView adapter with support for multiple choice modal selection

MultiChoiceAdapter MultiChoiceAdapter is an implementation of ListAdapter which adds support for modal multiple choice selection as in the native Gmai

Manuel Peinado Gallego 855 Nov 11, 2022
Epoxy is an Android library for building complex screens in a RecyclerView

Epoxy Epoxy is an Android library for building complex screens in a RecyclerView. Models are automatically generated from custom views or databinding

Airbnb 8.1k Jan 4, 2023
Android library to auto-play/pause videos from url in recyclerview.

AutoplayVideos Show some ❤️ and star the repo to support the project This library is created with the purpose to implement recyclerview with videos ea

Krupen Ghetiya 989 Nov 17, 2022
:page_with_curl: [Android Library] Giving powers to RecyclerView

Android library that provides most common functions around recycler-view like Swipe to dismiss, Drag and Drop, Divider in the ui, events for when item

Nishant Srivastava 644 Nov 20, 2022
Android library for the adapter view (RecyclerView, ViewPager, ViewPager2)

Antonio Android library for the adapter view (RecyclerView, ViewPager, ViewPager2) Free from implementation of the adapter's boilerplate code ! Reuse

NAVER Z 106 Dec 23, 2022
An Adapter that allows a RecyclerView to be split into Sections with headers and/or footers. Each Section can have its state controlled individually.

⚠️ Archived: this repository is no longer going to be maintained. SectionedRecyclerViewAdapter An Adapter that allows a RecyclerView to be split into

Gustavo Pagani 1.7k Dec 21, 2022
Create a new adapter for a RecyclerView or ViewPager is now much easier.

Efficient Adapter for Android Create a new adapter for a RecyclerView or ViewPager is now much easier. Overview Create a list of elements into a Recyc

Stan Kocken 423 Sep 16, 2022
Rx based RecyclerView Adapter

RxRecyclerAdapter Rx based generic RecyclerView Adapter Library. How to use it? Example! Enable Databinding by adding these lines to your build.gradle

Ahmed Rizwan 193 Jun 18, 2022
This Repository simplifies working with RecyclerView Adapter

AutoAdapter This Repository simplifies working with RecyclerView Adapter Gradle: Add it in your root build.gradle at the end of repositories: allproj

George Dzotsenidze 151 Aug 15, 2021
Generic RecyclerView adapter

Generic RecyclerView Adapter. Lightweight library which simplifies creating RecyclerView adapters and illuminates writing boilerplate code. Creating a

Leonid Ustenko 77 Dec 24, 2022
Open source routing engine for OpenStreetMap. Use it as Java library or server.

GraphHopper Routing Engine GraphHopper is a fast and memory efficient Java routing engine, released under Apache License 2.0. By default it uses OpenS

GraphHopper 4k Jan 7, 2023
The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...

FastAdapter The FastAdapter is here to simplify creating adapters for RecyclerViews. Don't worry about the adapter anymore. Just write the logic for h

Mike Penz 3.7k Jan 8, 2023
Vector map library and writer - running on Android and Desktop.

Mapsforge See the integration guide and changelog. And read through how to contribute guidelines. If you have any questions or problems, don't hesitat

mapsforge 1k Jan 2, 2023
A library to make a mosaic with a preview of multiple images

Preview Image Collection Introduction Preview Image Collection is a library to draw a collage with a number of images like facebook preview album Inst

Agnaldo Pereira 50 Jun 13, 2022