{"id":28901460,"url":"https://github.com/ericliu001/async-expandable-list","last_synced_at":"2025-09-10T16:34:26.383Z","repository":{"id":54914386,"uuid":"70774810","full_name":"Ericliu001/async-expandable-list","owner":"Ericliu001","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-07T06:04:16.000Z","size":152,"stargazers_count":222,"open_issues_count":4,"forks_count":50,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-07-07T07:23:26.490Z","etag":null,"topics":["async-expandable","collectionview","expandablerecyclerview","recyclerview","recyclerview-adapter","viewholder"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ericliu001.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-13T06:13:29.000Z","updated_at":"2025-07-07T06:04:20.000Z","dependencies_parsed_at":"2022-08-14T06:30:54.126Z","dependency_job_id":null,"html_url":"https://github.com/Ericliu001/async-expandable-list","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Ericliu001/async-expandable-list","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ericliu001%2Fasync-expandable-list","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ericliu001%2Fasync-expandable-list/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ericliu001%2Fasync-expandable-list/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ericliu001%2Fasync-expandable-list/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ericliu001","download_url":"https://codeload.github.com/Ericliu001/async-expandable-list/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ericliu001%2Fasync-expandable-list/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274487231,"owners_count":25294480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async-expandable","collectionview","expandablerecyclerview","recyclerview","recyclerview-adapter","viewholder"],"created_at":"2025-06-21T10:09:36.492Z","updated_at":"2025-09-10T16:34:26.372Z","avatar_url":"https://github.com/Ericliu001.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## This repository is no longer maintained by the author.\n\n\n# async-expandable-list\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Async%20Expandable%20List-green.svg?style=flat)](https://android-arsenal.com/details/1/5092)\n\n============\nasync-expandable-list contains 2 View classes: CollectionView and AsyncExpandableListView.\n\n\n![Demo](https://cloud.githubusercontent.com/assets/3691022/19348717/0d6c98ec-919b-11e6-97c3-a8ff782a059b.gif)  ![Demo](https://cloud.githubusercontent.com/assets/3691022/19406879/cb982648-92da-11e6-86bf-7c82e8505e6c.gif)\n\nAdd async-expandable-list to your project\n----------------------------\nGradle:\n```gradle\ncompile 'com.ericliu.asyncexpandablelist:asyncexpandablelist:1.1.0'\n```\n\n\nPlease make sure you have jcenter() in your project's repository. Check build.gradle file under the project's root directory. Add the following lines if they are missing. \n```gradle\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n```\n\nIntroduction\n-------------------\nCollectionView displays a list of headers and sub-items:\n   * Header A\n       * item a1\n       * item a2\n   * Header B\n       * item b1\n       * item b2\n       * item b3\n   * Header C\n       * item c1\n       * item c2\n       * item c3\n       \n       \nAsyncExpandableListView displays a list of headers and loads a sub-list under a header when a header item is clicked. The loading of sub-items can be done asynchronously and there are callbacks to populate the data into the list when it's done loading. \n\n \n 1. CollectionView in 3 steps\n-------------------\n1. Add the CollectionView to the layout.xml file where you want to display the list (Optional, population the CollectionView class in java has the same result)\n```xml\n\u003ccom.ericliu.asyncexpandablelist.CollectionView\n        android:id=\"@+id/collectionView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/\u003e\n\n```\n\n2. Pouplating data\n  * find the CollectionView instance and call setCollectionCallbacks() to setup callbacks for the CollectionView, which will be responsible for creating ViewHolders and binding data into the ViewHoders - works the same as the RecyclerView.Adapter except that you don't have to worry about view types.\n  * Create a CollectionView.Inventory instance, the Inventory instance represents the whole data structure that's gonna be populated into the list.\n    \n  \n  ```java\n public class MainActivity extends Activity implements CollectionViewCallbacks\u003cString, News\u003e {\n    private CollectionView\u003cString, News\u003e mCollectionView;\n    private CollectionView.Inventory\u003cString, News\u003e inventory;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        mCollectionView = (CollectionView) findViewById(R.id.collectionView);\n        mCollectionView.setCollectionCallbacks(this);\n        \n        // the inventory represent all the whole data structure that's gonna be populated into the list.\n        inventory = new CollectionView.Inventory\u003c\u003e();\n\n  ```\n  * Create InventoryGroup intances and add header item and sub-items into the InventoryGroup instance.\n  Note the the newGroup(int groupOrdinal) method provided in the Inventory class requires an integer parameter: groupOrdinal.\n  All the groups will be displayed in the list in an ascending order on the groupOrdinal.\n    An InventoryGroup represents a header item and all sub-items under that header in the list.\n    \n    \n  ```java\n        int groupOrdinal = 0; // groupOrdinal dictates the sequence of groups to be displayed in the list\n        CollectionView.InventoryGroup\u003cString, News\u003e group1 = inventory.newGroup(groupOrdinal); \n        \n        // creating objects to be populated into the list.\n        News news1 = new News();\n        ...  \n        News news2 = new News(); ......\n        .......\n        \n        // set the header item, in this case, it is simply a String.\n        group1.setHeaderItem(\"Top Stories\");\n        // add items under this header.\n        group1.addItem(news1);\n        group1.addItem(news2);\n        group1.addItem(news3);\n          ....\n  \n  ```\n  \n  * Call updateInventory() to display the data structure we just created\n  ```java\n   mCollectionView.updateInventory(inventory);\n  ```\n  All done, the list will display the exact header-items structure. \n  \n2. AsyncExpandableListView in 3 steps\n-------------------\n \n1. add AsyncExpandableListView to layout.xml file where you want to display the expandable list. (Optional, population the AsyncExpandableListView class in java has the same result).\n```xml\n\u003ccom.ericliu.asyncexpandablelist.async.AsyncExpandableListView\n        android:id=\"@+id/asyncExpandableCollectionView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/\u003e\n```\n2. Populating data\n  * find the AsyncExpandableListView and call setCallbacks() and supply an AsyncExpandableListViewCallbacks instance to the view. The callbacks will handle the creation of ViewHolders and binding data to the ViewHolders. \n  ```java\n  public class AsyncActivity extends Activity implements AsyncExpandableListViewCallbacks\u003cString, News\u003e {\n\n    private AsyncExpandableListView\u003cString, News\u003e mAsyncExpandableListView;\n    private CollectionView.Inventory\u003cString, News\u003e inventory;\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_async);\n        mAsyncExpandableListView = (AsyncExpandableListView) findViewById(R.id.asyncExpandableCollectionView);\n        mAsyncExpandableListView.setCallbacks(this);\n  \n  ```\n  \n  \n  * In particular the ``` void onStartLoadingGroup(int groupOrdinal) ``` method in the AsyncExpandableListViewCallbacks will be triggered on the header item click events, which gives the client a change to trigger loading sub-item data calls. When the call comes back, the client should call the method ``` onFinishLoadingGroup(mGroupOrdinal, items)``` on the AsyncExpandableListView instance to display the data as well as updating UI.\n  * The steps to add groups are the same as CollectionView mentioned above, but we don't need to add sub-items to groups at this point because only headers will be shown in the beginning in an expandable list, as the code snippet showed below:\n```java\n inventory = new CollectionView.Inventory\u003c\u003e();\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group1 = inventory.newGroup(0); // groupOrdinal is the smallest, displayed first\n        group1.setHeaderItem(\"Top Stories\");\n\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group2 = inventory.newGroup(2); // 2 is the second smallest ordinal, displayed second\n        group2.setHeaderItem(\"World\");\n\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group3 = inventory.newGroup(3);\n        group3.setHeaderItem(\"Australia\");\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group4 = inventory.newGroup(4); \n        group4.setHeaderItem(\"International\");\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group5 = inventory.newGroup(5); \n        group5.setHeaderItem(\"Businesses\");\n\n        CollectionView.InventoryGroup\u003cString, News\u003e group6 = inventory.newGroup(6); \n        group6.setHeaderItem(\"Technology\");\n\n        mAsyncExpandableListView.updateInventory(inventory);\n\n```\n\n3. Handle the async calls\n  * Making the call to load all sub-items under a header in the method onStartLoadingGroup() in the AsyncExpandableListViewCallbacks.\n  \n  ```java\n   @Override\n    public void onStartLoadingGroup(int groupOrdinal) {\n        new LoadDataTask(groupOrdinal, mAsyncExpandableListView).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);\n    }\n    ```\n  * When the data come back, call ``` onFinishLoadingGroup(mGroupOrdinal, items); ``` to display data. \n  ```java\n    mAsyncExpandableListView.onFinishLoadingGroup(mGroupOrdinal, items);\n  ```\n\nReferences:\n-------------------\nInspired by CollectionView in Google iosche\n\nhttps://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/CollectionView.java\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericliu001%2Fasync-expandable-list","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericliu001%2Fasync-expandable-list","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericliu001%2Fasync-expandable-list/lists"}