All Projects → arthur3486 → adapster

arthur3486 / adapster

Licence: Apache-2.0 License
Android library designed to enrich and make your RecyclerView adapters more SOLID

Programming Languages

java
68154 projects - #9 most used programming language
kotlin
9241 projects

Projects that are alternatives of or similar to adapster

Google Books Android Viewer
Android library to bridge between RecyclerView and sources like web page or database. Includes demonstrator (Google Books viewer)
Stars: ✭ 37 (+117.65%)
Mutual labels:  adapter, listview, recyclerview
Superadapter
[Deprecated]. 🚀 Adapter(BaseAdapter, RecyclerView.Adapter) wrapper for Android. 一个Adapter同时适用RecyclerView、ListView、GridView等。
Stars: ✭ 638 (+3652.94%)
Mutual labels:  adapter, listview, recyclerview
Boardview
A draggable boardview for java android (Kanban style)
Stars: ✭ 309 (+1717.65%)
Mutual labels:  adapter, listview, recyclerview
Commonadapter
一个适用于ListView/GridView/RecyclerView的Adapter库,简化大量重复代码,支持多种布局,可自定义图片加载的实现。
Stars: ✭ 219 (+1188.24%)
Mutual labels:  adapter, listview, recyclerview
recycler-adapter
RecyclerView-driven declarative UIs
Stars: ✭ 124 (+629.41%)
Mutual labels:  adapter, listview, recyclerview
Kotlin Adapter
🔥 RecyclerView,AbsListView适配器, 支持多种视图样式, 支持吸顶、侧滑删除、拖拽效果
Stars: ✭ 132 (+676.47%)
Mutual labels:  adapter, listview, recyclerview
Adapter
A quick adapter library for RecyclerView, GridView, ListView, ViewPager, Spinner
Stars: ✭ 376 (+2111.76%)
Mutual labels:  adapter, listview, recyclerview
GenericRecyclerAdapter
Easiest way to use RecyclerView. Reduce boilerplate code! You don't need to write adapters for listing pages anymore!
Stars: ✭ 53 (+211.76%)
Mutual labels:  adapter, listview, recyclerview
Easyadapter
Android 轻量级适配器,简化使用,适应所有的AbsListView、RecyclerView。支持HeaderView与FooterView~
Stars: ✭ 160 (+841.18%)
Mutual labels:  adapter, listview, recyclerview
GenericAdapter
⛳️ Easy to use android databinding ready recyclerview adapter
Stars: ✭ 26 (+52.94%)
Mutual labels:  adapter, listview, recyclerview
AdapterLayout
ViewGroup backed by RecyclerView.Adapter = magic
Stars: ✭ 58 (+241.18%)
Mutual labels:  adapter, recyclerview
MixAdapter
Compose multiple Adapter for RecyclerView in Android
Stars: ✭ 19 (+11.76%)
Mutual labels:  adapter, recyclerview
ARVI
Android library designed to simplify the implementation of the video autoplay in the RecyclerView
Stars: ✭ 69 (+305.88%)
Mutual labels:  adapter, recyclerview
PrimeAdapter
PrimeAdapter makes working with RecyclerView easier.
Stars: ✭ 54 (+217.65%)
Mutual labels:  adapter, recyclerview
PinnedSectionRecyclerView
simple RecyclerView with pinned sections for Android.
Stars: ✭ 21 (+23.53%)
Mutual labels:  listview, recyclerview
TheGreatAdapter
Multiple items adapter made too easy, including headers and footers.
Stars: ✭ 46 (+170.59%)
Mutual labels:  adapter, recyclerview
react-recycled-scrolling
Simulate normal scrolling by using only fixed number of DOM elements for large lists of items with React Hooks
Stars: ✭ 26 (+52.94%)
Mutual labels:  listview, recyclerview
InfiniteScroll
You can do a Endless scroll in ListView or RecyclerView with simple steps, with a listener for do request to your web service.
Stars: ✭ 28 (+64.71%)
Mutual labels:  listview, recyclerview
RecyclerViewAdapter
A RecyclerView Adapter that support load more and add headerview
Stars: ✭ 145 (+752.94%)
Mutual labels:  adapter, recyclerview
Modular2Recycler
Modular²Recycler is a RecyclerView.Adapter that is modular squared.
Stars: ✭ 72 (+323.53%)
Mutual labels:  adapter, recyclerview

Adapster

Android library designed to enrich and make your RecyclerView adapters more SOLID

Adapster will help you make your RecyclerView adapters more manageable and overall enrich your RecyclerView epxerience.

Download Android Arsenal License Platform

Contents

Demo (YouTube)

YouTube Video

Getting Started

  1. Make sure that you've added the jcenter() repository to your top-level build.gradle file.
buildscript {
    //...
    repositories {
        //...
        jcenter()
    }
    //...
}
  1. Add the library dependency to your module-level build.gradle file.

Latest version: Download

ext {
    //...
    adapsterLibraryVersion = "1.0.9"
}

dependencies {
    //...
    implementation "com.arthurivanets.adapster:adapster:$adapsterLibraryVersion"
}
  1. Enable the jetifier and androidX support in the top-level gradle.properties file.
//...
android.enableJetifier=true
android.useAndroidX=true
//....
  1. Update your compileSdkVersion in the module-level build.gradle file to 28+.
//...
android {
    //...
    compileSdkVersion 28
    //...
}
//...
  1. Update your com.android.support.appcompat.* dependency to the new androidx.appcompat.* alternative.
//...
dependencies {
    //...
    implementation "androidx.appcompat:appcompat:1.0.2"
    //...
}
//...
  1. Proceed with the implementation of your own adapter.

See: Basic RecyclerView-based Implementation and Basic ListView-based Implementation

Basic RecyclerView-based Implementation

Implementation of a basic RecyclerView-based concept involves 3 main steps - creation of concrete Item classes, creation of the adapter, and binding of the adapter to the RecyclerView.

Let's implement a basic RecyclerView-based concept by following the steps listed above:

  1. Creation of a concrete Item class that extends the BaseItem<IM, VH, IR> base class.
  • Creating a model class Article
Kotlin (click to expand)

data class Article(
    val id : Int,
    val title : String,
    val text : String,
    val imageUrl : String = ""
) {

    val hasImage : Boolean
        get() = !imageUrl.isBlank()

}

Java (click to expand)

public final class Article {

    private int id;
    private String title;
    private String text;
    private String imageUrl;

    public Article() {
    	this.id = -1;
    	this.title = "";
    	this.text = "";
    	this.imageUrl = "";
    }

    // Setters and Getters...

    public final boolean hasImage() {
    	return !TextUtils.isEmpty(this.imageUrl);
    }

}


  • Creating the ArticleItem item class for the Article model
Kotlin (click to expand)

class ArticleItem(itemModel : Article) : BaseItem<Article, ArticleItem.ViewHolder, ItemResources>(itemModel), Trackable<Int> {

    override fun init(adapter : Adapter<out Item<out RecyclerView.ViewHolder, out ItemResources>>,
                      parent : ViewGroup,
                      inflater : LayoutInflater,
                      resources : ItemResources?) : ViewHolder {
          // inflate (or create) your item view here and create a corresponding ViewHolder
          // then return the created ViewHolder
    }

    override fun bind(adapter : Adapter<out Item<out RecyclerView.ViewHolder, out ItemResources>>,
                      viewHolder : ViewHolder,
                      resources : ItemResources?) {
        super.bind(adapter, viewHolder, resources)

        // bind the data here
        // (use the itemModel associated with this item to access the data)
    }

    override fun getLayout() : Int {
        // return a unique id, which will be used as a View Type for this item
        // (you can use the item view layout id if this item's view is not going
        // to be modified dynamically by adding new views to it, otherwise you will
        // have to compose your own id to properly distinguish the item's view within your adapter)
        return R.layout.article_item_layout
    }

    override fun getTrackKey() : Int {
        // use the model's unique id to prevent the duplicates within the Adapter
        // (this step is optional and is enabled by the implementation of the Trackable<KeyType> interface)
        return itemModel.id
    }

    class ViewHolder(itemView : View) : BaseItem.ViewHolder<Article>(itemView) {

        // look up (or initialize) your views here...

    }

}

Java (click to expand)

public final class ArticleItem extends BaseItem<Article, ArticleItem.ViewHolder, ItemResources> implements Trackable<Integer> {

    public ArticleItem(Article itemModel) {
        super(itemModel);
    }

    @Override
    public ViewHolder init(Adapter<? extends Item> adapter,
                           ViewGroup parent,
                           LayoutInflater inflater,
                           ItemResources resources) {
          // inflate (or create) your item view here and create a corresponding ViewHolder
          // then return the created ViewHolder
    }

    @Override
    public void bind(Adapter<? extends Item> adapter,
                     ViewHolder viewHolder,
                     ItemResources resources) {
        super.bind(adapter, viewHolder, resources);

        // bind the data here
        // (use the itemModel associated with this item to access the data)
    }
    
    @Override
    public int getLayout() {
        // return a unique id, which will be used as a View Type for this item
        // (you can use the item view layout id if this item's view is not going
        // to be modified dynamically by adding new views to it, otherwise you will
        // have to compose your own id to properly distinguish the item's view within your adapter)
        return R.layout.article_item_layout;
    }

    @Override
    public int getTrackKey() {
        // use the model's unique id to prevent the duplicates within the Adapter
        // (this step is optional and is enabled by the implementation of the Trackable<KeyType> interface)
        return getItemModel().getId();
    }

    public static class ViewHolder extends BaseItem.ViewHolder<Article> {

        public ViewHolder(View itemView) {
	    super(itemView);

            // look up (or initialize) your views here...
        }

    }

}


  1. Creation of the adapter that extends the TrackableRecyclerViewAdapter<KT, IT, VH> base class.
  • Creating the ArticlesRecyclerViewAdapter
Kotlin (click to expand)

class ArticlesRecyclerViewAdapter(
    context : Context,
    items : MutableList<ArticleItem>
) : TrackableRecyclerViewAdapter<Long, ArticleItem, ArticleItem.ViewHolder>(context, items) {

    var onArticleItemClickListener : OnItemClickListener<ArticleItem>? = null

    init {
        setHasStableIds(true)
    }

    override fun assignListeners(holder : ArticleItem.ViewHolder, position : Int, item : ArticleItem) {
        super.assignListeners(holder, position, item)

        item.setOnItemClickListener(holder, onArticleItemClickListener)
    }

}

Java (click to expand)

public final class ArticlesRecyclerViewAdapter extends TrackableRecyclerViewAdapter<Long, ArticleItem, ArticleItem.ViewHolder> {

    private OnItemClickListener<ArticleItem> onArticleItemClickListener;

    public ArticlesRecyclerViewAdapter(Context context, List<ArticleItem> items) {
        super(context, items);
        setHasStableIds(true);
    }

    @Override
    public void assignListeners(ArticleItem.ViewHolder holder, int position, ArticleItem item) {
        super.assignListeners(holder, position, item);

        item.setOnItemClickListener(holder, onArticleItemClickListener);
    }

    public final void setOnItemClickListener(OnItemClickListener<ArticleItem> onArticleItemClickListener) {
        this.onArticleItemClickListener = onArticleItemClickListener;
    }

}


  1. Instantiation of the created adapter and its binding to the RecyclerView.
  • Instantiating the ArticlesRecyclerViewAdapter, setting the Adapter-specific listeners, and binding the adapter to the RecyclerView
Kotlin (click to expand)

//...
private var items = ArrayList<ArticleItem>()
private lateinit var adapter : ArticlesRecyclerViewAdapter

//...
private fun initRecyclerView() {
    //...
    adapter = ArticlesRecyclerViewAdapter(this, items)
    adapter.onArticleItemClickListener = OnItemClickListener { view, item, position ->
        // handle the article item click
    }

    //...
    recyclerView.adapter = adapter
}
//...

Java (click to expand)

//...
private List<ArticleItem> items = new ArrayList<>();
private RecyclerView recyclerView;
private ArticlesRecyclerViewAdapter adapter;

//...
private void initRecyclerView() {
    //....
    recyclerView = findViewById(R.id.recyclerView);

    //...
    adapter = new ArticlesRecyclerViewAdapter(this, items);
    adpater.setOnArticleItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClicked(View view, ArticleItem item, int position) {
            // handle the article item click
        }
    });

    //...
    recyclerView.setAdapter(adapter);
}

Basic ListView-based Implementation

Implementation of a basic ListView-based concept is identical to the Basic RecyclerView-based Implementation, with the exception of one thing - the adapter implementation.

In the ListView-based concept your adapter should be provided with a little more information about the nature of the items it's handling, such as the exact View Type Count the adapter is going to handle, and Item View Type for a given adapter position (This additional information is only required in cases when you have more than one View Type associated with the Adapter).

Here's the implementation of the ArticlesListViewAdapter

Kotlin (click to expand)

class ArticlesListViewAdapter(
    context : Context,
    items : MutableList<ArticleItem>
) : TrackableListViewAdapter<Long, ArticleItem, ArticleItem.ViewHolder>(context, items) {

    var onItemClickListener : OnItemClickListener<ArticleItem>? = null

    override fun assignListeners(holder : ArticleItem.ViewHolder, position : Int, item : ArticleItem) {
        super.assignListeners(holder, position, item)

        item.setOnItemClickListener(holder, onItemClickListener)
    }

}

Java (click to expand)

public final class ArticlesListViewAdapter extends TrackableListViewAdapter<Long, ArticleItem, ArticleItem.ViewHolder> {

    private OnItemClickListener<ArticleItem> onItemClickListener;

    public ArticlesListViewAdapter(Context context, List<ArticleItem> items) {
        super(context, items);
        setHasStableIds(true);
    }

    @Override
    public void assignListeners(ArticleItem.ViewHolder holder, int position, ArticleItem item) {
        super.assignListeners(holder, position, item);

        item.setOnItemClickListener(holder, onItemClickListener);
    }

    public final void setOnItemClickListener(OnItemClickListener<ArticleItem> onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

}

Advanced Use

  • Header and Footer Support
    To add a Header and/or Footer to your RecyclerView you need to create an Item class that extends the BaseItem<IM, VH, IR> and implement the marker interface Header<VH> (or Footer<VH>) on it (but not both at the same time). Thereafter you will be able to provide the implementation for the interface methods.

The implementation of the aforementioned marker interfaces will allow the adapter to properly distinguish and handle the items; the Header Item will always be placed at the top, while the Footer - at the bottom.

IMPORTANT: To be able to properly utilize this functionality (Header and/or Footer support) you must first make sure that the adapter you're using has that support provided to you. An adapter that supports Header and/or Footer must implement the SupportsHeader<VH> and/or SupportsFooter<VH> interfaces and the corresponding interface methods. There's no need to worry about this nuance if you're using the library-provided adapter implementations (such as TrackableRecyclerViewAdapter<KT, IT, VH> and TrackableListViewAdapter<KT, IT, VH>), as they do provide the support for both the Header and Footer; otherwise, if you decide to implement your own adapter based on the contracts provided by the library you should consider implementing the aforementioned interfaces to provide the desired Header and/or Footer support.

Adapters that have the Header and/or Footer support provide the following list of convenience-methods:
Header-related
addHeader(Header<VH>)
removeHeader()
setOnHeaderClickListener(OnItemClickListener<Header<VH>>)
Footer-related
addFooter(Footer<VH>)
removeFooter()
setOnFooterClickListener(OnItemClickListener<Footer<VH>>)
These methods will help you manage the Header and/or Footer within your adapter.

Here's an example of how to create a Header Item and what changes need to take place in the Adapter.

  • Creating a TopicHeaderItem
Kotlin (click to expand)

class TopicItem(itemModel : Topic) : BaseItem<Topic, TopicItem.ViewHolder, ItemResources>(itemModel),
        Header<BaseItem.ViewHolder<*>> {

    override fun init(adapter : Adapter<out Item<out RecyclerView.ViewHolder, out ItemResources>>,
                      parent : ViewGroup,
                      inflater : LayoutInflater,
                      resources : ItemResources?) : ViewHolder {
        return ViewHolder(inflater.inflate(
            layout,
            parent,
            false
        ))
    }

    override fun bind(adapter : Adapter<out Item<out RecyclerView.ViewHolder, out ItemResources>>,
                      viewHolder : ViewHolder,
                      resources : ItemResources?) {
        super.bind(adapter, viewHolder, resources)

        viewHolder.nameTv.text = itemModel.name

        Picasso.with(viewHolder.imageIv.context.applicationContext)
            .load(itemModel.imageUrl)
            .into(viewHolder.imageIv)
    }

    override fun setOnItemClickListener(viewHolder : BaseItem.ViewHolder<*>, onItemClickListener : OnItemClickListener<Header<BaseItem.ViewHolder<*>>>?) {
        viewHolder.itemView.setOnClickListener(ItemClickListener(this, 0, onItemClickListener))
    }

    override fun getLayout() : Int {
        return R.layout.topic_item_layout
    }

    class ViewHolder(itemView : View) : BaseItem.ViewHolder<Topic>(itemView) {

        val imageIv = itemView.findViewById<ImageView>(R.id.imageIv)
        val nameTv = itemView.findViewById<TextView>(R.id.nameTv)

    }

}

Java (click to expand)

public final class TopicItem extends BaseItem<Topic, TopicItem.ViewHolder, ItemResources> implements
        Header<BaseItem.ViewHolder> {

    public TopicItem(Topic itemModel) {
        super(itemModel);
    }

    @Override
    public ViewHolder init(Adapter<? extends Item> adapter,
                           ViewGroup parent,
                           LayoutInflater inflater,
                           ItemResources resources) {
        return new ViewHolder(inflater.inflate(
            getLayout(),
            parent,
            false
        ));
    }

    @Override
    public void bind(Adapter<? extends Item> adapter,
                     ViewHolder viewHolder,
                     ItemResources resources) {
        super.bind(adapter, viewHolder, resources);

        viewHolder.nameTv.setText(getItemModel().getName());

        Picasso.with(viewHolder.imageIv.getContext().getApplicationContext())
            .load(getItemModel().getImageUrl())
            .into(viewHolder.imageIv);
    }

    @Override
    public void setOnItemClickListener(BaseItem.ViewHolder viewHolder, OnItemClickListener<Header<BaseItem.ViewHolder>> onItemClickListener) {
        viewHolder.itemView.setOnClickListener(new ItemClickListener(this, 0, onItemClickListener));
    }

    @Override
    public int getLayout() {
        return R.layout.topic_item_layout;
    }

    public static final class ViewHolder extends BaseItem.ViewHolder<Topic> {

        ImageView imageIv;
        TextView nameTv;

        public ViewHolder(View itemView) {
            super(itemView);
            imageIv = itemView.findViewById(R.id.imageIv);
            nameTv = itemView.findViewById(R.id.nameTv);
        }

    }

}


  • Altering the adapters - now we need to enable the Multi-item support (See Adapter multi-item support below)

  • Adapter multi-item support
    To enable the support of multiple item types in your adapter you need to change adapter item type to a more general one (e.g. BaseItem) (For ListView-based adapters you should also specify the exact View Type Count and the actual Item View Type for a given position).

Here's an example of a multi-item adapter that supports Header and Footer items.

Kotlin (click to expand)

class SimpleRecyclerViewAdapter(
	context : Context,
	items : MutableList<BaseItem<*, *, *>>
) : TrackableRecyclerViewAdapter<Long, BaseItem<*, *, *>, BaseItem.ViewHolder<*>>(context, items) {

    var onArticleItemClickListener : OnItemClickListener<ArticleItem>? = null
    var onTopicSuggestionItemClickListener : OnItemClickListener<TopicSuggestionItem>? = null
    var onTopicSuggestionItemLongClickListener : OnItemLongClickListener<TopicSuggestionItem>? = null
    var onFooterButtonClickListener : OnItemClickListener<FooterItem>? = null

    init {
        setHasStableIds(true)
    }

    override fun assignListeners(holder : BaseItem.ViewHolder<*>, position : Int, item : BaseItem<*, *, *>) {
        super.assignListeners(holder, position, item)

        when(item) {
            is ArticleItem -> onArticleItemClickListener?.let { item.setOnItemClickListener((holder as ArticleItem.ViewHolder), it) }
            is FooterItem -> onFooterButtonClickListener?.let { item.setOnButtonClickListener((holder as FooterItem.ViewHolder), it) }
            is TopicSuggestionsItem -> {
                onTopicSuggestionItemClickListener?.let { item.setOnItemClickListener((holder as TopicSuggestionsItem.ViewHolder), it) }
                onTopicSuggestionItemLongClickListener?.let { item.setOnItemLongClickListener((holder as TopicSuggestionsItem.ViewHolder), it) }
            }
        }
    }

}

Java (click to expand)

public final class SimpleRecyclerViewAdapter extends TrackableRecyclerViewAdapter<Long, BaseItem, BaseItem.ViewHolder> {

    private OnItemClickListener<ArticleItem> onArticleItemClickListener;
    private OnItemClickListener<TopicSuggestionItem> onTopicSuggestionItemClickListener;
    private OnItemLongClickListener<TopicSuggestionItem> onTopicSuggestionItemLongClickListener;
    private OnItemClickListener<FooterItem> onFooterButtonClickListener;

    public SimpleRecyclerViewAdapter(Context context, List<BaseItem> items) {
        super(context, items);
        setHasStableIds(true);
    }

    @Override
    public void assignListeners(BaseItem.ViewHolder holder, int position, BaseItem item) {
        super.assignListeners(holder, position, item);
		
		if(item instanceof ArticleItem) {
			((ArticleItem) item).setOnItemClickListener(((ArticleItem.ViewHolder) holder), onArticleItemClickListener);
		} else if(item instanceof FooterItem) {
			((FooterItem) item).setOnButtonClickListener(((FooterItem.ViewHolder) holder), onFooterButtonClickListener);
		}
    }

    // Listener setters...

}


The sample ListView-based multi-item adapter implementation can be found here SimpleListViewAdapter.kt

Data Binding

  • Data Binding Support
    First, make sure the adapster-databinding dependency is added to your build.gradle file, as well as the core adapster one.
ext {
    //...
    adapsterLibraryVersion = "1.0.9"
}

dependencies {
    //...
    implementation "com.arthurivanets.adapster:adapster:$adapsterLibraryVersion"
    implementation "com.arthurivanets.adapster:adapster-databinding:$adapsterLibraryVersion"
}

//TODO to be continued

Contribution

See the CONTRIBUTING.md file.

Hall of Fame

Reminder
Owly
Stocks Exchange

Using Adapster in your app and want it to get listed here? Email me at [email protected]!

License

Adapster is licensed under the Apache 2.0 License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].