User Profile Hosting Page Design
This feature is supported starting from version 5.12.0.
Page Architecture Design
The User Profile Hosting adopts the MVVM (Model-View-ViewModel) pattern, combining Android's Fragment and Activity lifecycle management with a layered decoupling design philosophy. Each layer has clearly defined responsibilities in the architecture, aiming to improve code readability, maintainability, and extensibility.
- Activity: Serves as the entry point of the page, responsible for loading and displaying Fragments and passing necessary parameters.
- Fragment: Handles UI display and user interaction logic, fetching data through ViewModel and updating views.
- ViewModel: Acts as the intermediary layer for data and business logic, processing data retrieval, manipulation, and updates, and notifying Fragments of data changes.
- Handler: Serves as the core layer for business data processing, encapsulating specific implementations of data retrieval and operations, and providing interfaces for data manipulation.
- Component: Encapsulates commonly used UI controls and interaction logic to enhance component reusability.
- XML Layout Files: Define the structure, style, and layout of views, providing UI support for Fragments.

Page Architecture Hierarchy
Activity Layer
- Role:
- Serves as the entry point of the page, responsible for initializing and loading Fragments.
- Manages page navigation, parameter passing, and communication between Fragments.
Fragment Layer
- Role:
- Acts as the primary layer for UI display and interaction logic, responsible for loading and managing view components.
- Handles user interaction events such as button clicks and input field changes.
- Observes data changes through ViewModel and updates views accordingly.
- Custom Methods:
onCreateViewModel():- Creates a ViewModel instance via ViewModelProvider. Can be overridden to return a custom ViewModel class.
onCreateView():- Calls the parent class's layout loading logic via
super.onCreateView()and adds or adjusts custom views on top of the parent class.
- Calls the parent class's layout loading logic via
onViewReady():- Binds LiveData, sets click event listeners, and updates the UI.
ViewModel Layer
- Role:
- Acts as the bridge between Fragments and the data layer, managing and processing business logic.
- Notifies Fragments of data changes via mechanisms like LiveData.
- Calls Handlers for data retrieval, updates, or submissions.
- Custom Methods:
- Add new business logic processing methods or create new LiveData properties.
Handler Layer
- Role:
- Serves as the concrete implementation layer for data operations, encapsulating calls to data sources to avoid memory leaks.
- Provides methods for data retrieval, saving, updating, and deletion, offering interfaces for ViewModel.
Component Layer
- Role:
- Encapsulates commonly used view components to improve reusability.
XML Layout File Layer
- Role:
- Defines the structure, style, and layout of views, forming the foundation for UI display.
- Allows quick definition and modification of view structures through layout files.

Customization Guide
Role of KitFragmentFactory
KitFragmentFactory is a factory class in Kit for creating Fragments, enabling developers to flexibly manage and replace Fragments. By extending KitFragmentFactory and overriding methods like newGroupProfileFragment(), you can return a custom GroupProfileFragment.
public class CustomKitFragmentFactory extends KitFragmentFactory {
@NonNull
@Override
public GroupProfileFragment newGroupProfileFragment(@NonNull Bundle args) {
CustomGroupProfileFragment fragment = new CustomGroupProfileFragment();
fragment.setArguments(args);
return fragment;
}
}
// Set the custom factory during IMUIKit initialization in the Application class:
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
// Set the custom Fragment factory
IMCenter.setKitFragmentFactory(new CustomKitFragmentFactory());
}
}
Customizing Fragments
-
Scope:
- Override
onCreateView()andonViewReady()to add custom view components and interaction logic. - Handle specific UI logic and user interactions, such as button clicks or page refreshes.
- Override
-
Recommendations:
- Delegate all business logic to
ViewModel, withFragmentfocusing solely on UI display and user interaction event handling. - Fetch data and observe changes via
ViewModel, avoiding direct interaction with data sources.
- Delegate all business logic to
// Custom Fragment (e.g., CustomGroupProfileFragment)
public class CustomGroupProfileFragment extends GroupProfileFragment {
// Override to return a custom ViewModel (e.g., CustomGroupProfileViewModel)
@Override
protected GroupProfileViewModel onCreateViewModel(Bundle bundle) {
return new ViewModelProvider(this, new ViewModelFactory(bundle))
.get(CustomGroupProfileViewModel.class);
}
@Override
protected void onViewReady(@NonNull GroupProfileViewModel viewModel) {
super.onViewReady(viewModel);
// Change the title text
headComponent.setTitleText("New Title");
// Override the back button click event in the title bar
headComponent.setLeftClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Custom back button logic
}
});
// Override the right button click event in the title bar (if applicable)
headComponent.setRightClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Custom right button logic
}
});
// Set the right button icon in the title bar
headComponent.setRightTextDrawable(R.drawable.rc_right_icon);
}
}
Customizing ViewModel
-
Scope:
- Add custom business logic methods, such as data filtering or transformation.
- Create new
LiveDataproperties for Fragments to observe data changes.
-
Recommendations:
- Encapsulate all business logic in
ViewModel, avoiding logic inFragmentorHandler. - Use
Handlerfor data retrieval and operations, preventing direct interaction with data sources inViewModel.
- Encapsulate all business logic in
// Custom ViewModel (e.g., CustomGroupProfileViewModel)
public class CustomGroupProfileViewModel extends GroupProfileViewModel {
public CustomGroupProfileViewModel(@NonNull Bundle arguments) {
super(arguments);
}
// Add custom business logic
}
Customizing XML Layout Files
-
Scope:
- Copy the original Kit page's XML layout files to the app's
res/layoutdirectory and modify or add view components as needed. - Define custom view attributes and styles, such as colors, sizes, and spacing.
- Copy the original Kit page's XML layout files to the app's
-
Notes:
- Do not delete original views: Even if certain default views are unnecessary, avoid deleting them. Instead, hide them by setting
visibilitytoGONEorINVISIBLE. - Do not modify original view IDs: Changing original view IDs may cause
GroupProfileFragmentlogic to malfunction.
- Do not delete original views: Even if certain default views are unnecessary, avoid deleting them. Instead, hide them by setting
Handler Function Overview
Role: Serves as the core layer for business data processing, encapsulating concrete implementations of data retrieval and operations, and providing interfaces for data manipulation.
GroupInfoHandler
GroupInfoHandler is primarily used to fetch basic group information and details of specified members, with DataKey identifying different data operation types for easy monitoring and handling. Below are the external interface descriptions and DataKey definitions for GroupInfoHandler:
public class GroupInfoHandler extends MultiDataHandler {
// DataKey for fetching group information
public static final DataKey<GroupInfo> KEY_GROUP_INFO =
MultiDataHandler.DataKey.obtain("KEY_GROUP_INFO", GroupInfo.class);
// DataKey for fetching group member information
public static final DataKey<List<GroupMemberInfo>> KEY_GET_GROUP_MEMBERS =
MultiDataHandler.DataKey.obtain("KEY_GET_GROUP_MEMBERS",
(Class<List<GroupMemberInfo>>) (Class<?>) List.class);
// DataKey for searching group members
public static final DataKey<List<GroupMemberInfo>> KEY_SEARCH_GROUP_MEMBERS =
MultiDataHandler.DataKey.obtain("KEY_SEARCH_GROUP_MEMBERS",
(Class<List<GroupMemberInfo>>) (Class<?>) List.class);
/**
* Fetch group information
* @description Fetches detailed information of the specified group and notifies the caller via listener callback.
*/
public void getGroupsInfo() {
// Fetches detailed group information (e.g., group name, announcement, avatar) from the server.
// Results are returned via listener callback: group info on success, error code on failure.
}
/**
* Fetch group member information
* @param userIds List of user IDs
* @description Fetches group member information for the specified user IDs and notifies the caller via listener callback.
*/
public void getGroupMembers(List<String> userIds) {
// Fetches detailed member information (e.g., role, join time) for the specified user IDs in the current group.
// Results are returned via listener callback: member info list on success, error code on failure.
}
/**
* Search group members
* @param name Member name
* @description Searches group members by name and notifies the caller via listener callback.
*/
public void searchGroupMembers(String name) {
// Searches for member information matching the name in the current group.
// Results are returned via listener callback: member info list on success, error code on failure.
}
}
DataKey Descriptions
- KEY_GET_GROUP_MEMBERS: Identifies the data key for fetching group member information, type:
List<GroupMemberInfo>. - KEY_TOTAL_GROUP_MEMBERS: Identifies the data key for total group member count, type: Integer.
- KEY_LOAD_MORE: Identifies the data key for whether more group member data can be loaded, type: Boolean.
GroupMembersPagedHandler
GroupMembersPagedHandler is used to fetch group member lists in a paginated manner, supporting fetching by role and providing load-more functionality. Below are the external interface descriptions and DataKey definitions for GroupMembersPagedHandler:
public class GroupMembersPagedHandler extends MultiDataHandler {
// DataKey for fetching group member information
public static final DataKey<List<GroupMemberInfo>> KEY_GET_GROUP_MEMBERS =
MultiDataHandler.DataKey.obtain("KEY_GET_GROUP_MEMBERS",
(Class<List<GroupMemberInfo>>) (Class<?>) List.class);
// DataKey for whether more group member data can be loaded
private static final DataKey<Boolean> KEY_LOAD_MORE =
DataKey.obtain("KEY_LOAD_MORE", Boolean.class);
/**
* Fetch group member information
* @param groupMemberRole Group member role
* @description Fetches member lists by specified role (e.g., owner, admin, regular member) with pagination support.
*/
public void getGroupMembersByRole(@NonNull GroupMemberRole groupMemberRole) {
// Fetches member lists by role with pagination.
// Results are returned via listener callback: member list on success, error code on failure.
}
/**
* Load next page of group member data
* @param listener Data change listener
* @description Loads more group member information and notifies the caller via listener callback.
*/
public void loadNext(OnDataChangeListener<Boolean> listener) {
// Loads the next page of data for the current member role.
// Returns true via listener on success, false otherwise.
}
/**
* Check if more data is available
* @description Checks if more group member data can be loaded.
* @return true if more data is available, false otherwise.
*/
public boolean hasNext() {
// Returns whether more data can be loaded.
return !TextUtils.isEmpty(nextPageToken);
}
}
DataKey Descriptions
- KEY_GET_GROUP_MEMBERS: Identifies the data key for fetching group member information, type:
List<GroupMemberInfo>. - KEY_TOTAL_GROUP_MEMBERS: Identifies the data key for total group member count, type: Integer.
- KEY_LOAD_MORE: Identifies the data key for whether more group member data can be loaded, type: Boolean.