Hiya everybody 🙋♂️ On this half I’ll present the demo app of Clear App Base Library.
What does this app?
It will get customers from a server and lists them. If any consumer clicked a element web page opened. Within the element web page consumer particulars and modifying profile image applied as two tabs.
It makes use of Fakejson as the information supply. It’s a actually good software to mock a server. It might probably reply the way you need the reply or can reply built-in information or listing.
Construction
It’s an one-module app that consists of three packages. I named each bundle as an app function. These are: core
, element
and predominant
. They’re all divided by three acquainted packages: information
,area
and presentation
. They’re all related with Koin dependency injection library.
core
bundle consists of app extensive base courses ,community specs and CABDemoApp class. element
bundle consists of profile element screens and options. predominant
bundle consists of predominant web page screens and options. Let’s look at one after the other:
core bundle consists of all app-specific base courses. Once you accomplished the core bundle based mostly of Clear Software Base library, improvement of options turns into very simple.
core.information
This bundle handles information layer base courses and fashions. Due to our information supply is just community, it incorporates community courses principally. It additionally has a base DataSource and ApiCallAdapter implementation.
Networking is an app-specific function. Server addresses, server request-response sorts, authentications and periods differ app to app. Initially I created server information fashions.
There are some json request and response examples to grasp higher above constructions:
Within the request: information
, parameters
and token
despatched to server. information
is what we wish from the server as a response information. parameters
are api properties to handle how we wish the information. token
is required to get information from the api.
Within the response: Solely our information sort is returned from the server.(ResponseTemplate<T>). Right here T is ProfileDetail mannequin which resides intimately bundle.
However how this information is processed?
Changing server textual content information to our courses carried out by ApiCallAdapter. It’s a base class for app particular implementations.
It takes a lambda perform to deal with service calls. The perform returns a subclass of BaseApiResponse<T>
Right here is the implementation of ApiCAllAdapter. It have to be app particular as a result of server responses and dealing with is completely different at each app.
It handles retrofit calls and produces a DataHolder<T> based on server statuses. It additionally handles error circumstances corresponding to unsuitable response format, invalid token and no web situations. It executes response as a attempt,catch block, so there will probably be no runtime crash due to these errors.
BaseDataSource is a app-specific base class for CAB DataSource. It may be used to intercept all information sources and modify them. It isn’t used to change information for now however I added to demonstration functions:
It’s a base for AsyncDataSource.RequestDataSource. It may also be applied for different information supply sorts.
core.area
This bundle has Base Interactors and RequestResultType mannequin. Once more there isn’t any have to create Base class for interactors. It’s created for simply demonstration functions.
core.presentation
This bundle has base Exercise
, Fragment
and ViewModel
. Moreover it has navigation and UI helper courses. These element bases really simply implement the CAB library element interfaces. Let’s have a look at them:
They’re applied the CAB library to forestall each function element implementing it time and again. All function parts are childs of this bundle base element courses.
Navigation
Navigation is once more an app-specific challenge. You should utilize multi-activity
, single-activity
or hybrid
navigation methods. I used a navigation helper class to supply a easy navigation between actions. It has an Interface named NavigatorOwner that gives an AppNavigator. It’s applied by CABDemoBaseActivity, so each little one exercise
may have this navigation helper class. The AppNavigator occasion offered by the DI
.
CAB library has a helper class named IntentLoader to navigate between modules through the use of exercise’s full class identify in modular initiatives.
This bundle additionally incorporates CabDemoApp class. Once more App class is an app-specific class so it should belong right here. This class is required to initialize DI
.
core
bundle has the principle implementation code of CAB library.
We’ll proceed with the function packages, so I recommend taking a espresso break 🙂
Let’s have a look at function packages to how CAB library properties is used through core bundle:
This bundle is chargeable for exhibiting the consumer listing as a primary display screen. It should additionally navigate to element display screen when a row in listing clicked. This bundle additionally has information
, area
and presentation
layers. When the consumer enter the app MainActivity opened. Then it reveals a dialog utilizing CABActivity extension strategies. Within the dialog consumer requested to decide on get Fail or Succes information. If the consumer selects fail an error dialog is proven. In any other case information is requested from the server and RecyclerView is populated.
predominant.information
It has its personal fashions, information sources, repository implementation and DI module. All the things associated with the principle information is applied right here. It strikes information to the higher layer through repository. Let’s have a look at them:
Top notch is the request mannequin. We request a listing mannequin from api. That is utilization of api’s particular person create function. It creates a random particular person with requested properties.
Second class is a community information switch object mannequin. This mannequin belongs to the information layer. It’s an enterprise mannequin so it have to be transformed to an app mannequin which resides within the area layer. This dialog is offered by mapToUserListItem()
extension perform. As you may see it converts the server date string to Date object in desired format. It additionally generates a working picture url hyperlink from userId
(personNickName
).
GetUsersDataSource is the information supply implementation of predominant.information
It takes consumer service and ApiCallAdapter as variables. It simply calls adapt
perform of ApiCAllAdapter. Its request sort is ResponseTemplate<UserListDataTemplate> and return sort is DataHolder<Checklist<UserListItemNetworkDTO>>
UserService is an interface with a perform annotated with Retrofit annotation. It really will get information from the server.
It’s a droop
perform. Meaning it may be referred to as from one other droop
perform. If you happen to bear in mind all features are droop
features as much as viewModel
within the name chain.
ApiCall adapter is offered by DI at core.information
bundle. It’s offered as a Singleton
object so all information sources use the identical name adapter.
The ultimate class to look at is UserRepositoryImpl.
Repository is the place that the enterprise logic have to be applied. DataSources are chargeable for solely getting information within the type of information layer fashions. Mixing information sources, filtering or reworking fashions are job of the repository. On this state of affairs the server returns a profitable response if there isn’t any different error. However we wish to see error response from the server.(with our information sorts). So we offer a RequestTemplate<UserListDataTemplate> to the information supply as parameter that what sort of end result we wish. Then we put information to be returned from the server(UserListDataTemplate or Error). Lastly execute information supply and return information mapped to Checklist<UserListItem>, which is an utility mannequin if the execution result’s DataHolder.Success. In any other case return DataHolder to the interactor with out intercepting.
However how are they related?
The reply is dependency injection. I outlined all class creation definitions in MainDataModule.
manufacturing unit{} means everytime the article requested create a brand new occasion for it. By that means, the occasion will probably be faraway from reminiscence when there isn’t any reference to it. So they won’t trigger a reminiscence leak after the consumer ViewModel is closed.
named<T>
is used as a result of there are different implementations of BaseDataSource. So we should inform to DI this: Give me a BaseDataSource but it surely have to be GetUserDataSource. However why didn’t we requested GetUserDataSource straight? As a result of UserRepositoryImpl takes a constructor parameter sort of BaseDataSource<ResponseTemplate<UserListDataTemplate>,
Checklist<UserListItemNetworkDTO>>. So administration of the DI is essential if we don’t wish to battle with the runtime errors.
predominant.area
This bundle has the appliance information mannequin, interactor and the repository interface. Software information mannequin has app or platform class sort variables. So we will use it within the presentation layer.
Since our function does one job(Getting consumer listing) there’s one interactor. Our interactor is GetUsersInteractor:
It takes a userRepository
on the constructor. Its sort is a generic sort of BaseSingleInteractor<GetUsersInteractor.Params,Checklist<UserListItem>>
Param is an interactor particular sort. It supplies separation of knowledge and presentation layers.
It has an override perform: executeInteractor(params:GetUsersInteractor.Params)
. Person of this interactor should name solely this perform with the required parameters.
predominant.presentation
It consists of three courses: MainPresentationModule, MainActivity and MainViewModel. MainPresentationModule supplies MainViewModel through Koin DI
:
It’s binded to CABDemoBaseViewModel as a result of DialogHolder expects CABDemoBaseActivity(which is the guardian class of MainActivity) to supply a CABViewModel(which is the guardian class of CABDemoBaseViewModel)
MainViewModel executes the interactor and passes the end result to a LiveData<Checklist<UserListItem>.
It takes a Interactor.SingleInteractor<GetUsersInteractor.Params,Checklist<UserListItem>> as a constructor parameter. Once more it isn’t Interactor itself, it’s base class. It offers an enormous benefit to us when unit testing. It has _usersLiveData
and usersLiveData
. First one is a MutableLiveData to change within the class. The opposite one is a LiveData to show our reside information to exterior. We don’t wish to our reside information to be modified exterior of this class.
To get customers from api, getUsers()
perform is known as. It simply calls execInteractor()
perform of the CABViewModel extension. Beneath the hood, it makes _usersLiveData
’s worth to DataHolder.Loading. Then executes the interactor and posts end result to _usersLiveData
. Search for half 2 for additional particulars.
Within the MainActivity, this execution is triggered and outcomes are noticed. Let’s look inside it:
In MainActivity the consumer is requested to pick the success or fail state of knowledge that will probably be taken from the server through askForSuccessOrFail()
perform. It’s requested in two locations: In onStart()
methodology and in button click on callback of error dialog. Then based on state the information view mannequin’s getUsers(requestResultType: RequestResultType)
perform is known as.
In onCreate()
perform view mannequin’s userLiveData
is listened through observeDataHolder()
extension perform of SAPActivity.
It mainly manages dialogs based on reside information state. Above code, it takes three parameters. First: liveData
— LiveData to watch. Second: errorButtonClick
— present error or success dialog to consumer once more when error dialog button clicked. Third: successBody
— fill recycler view when information holder result’s success.
That is the tip of predominant bundle.
The remaining bundle/function is element . It’s information and area layers are principally the identical as predominant bundle. Since this half is kind of lengthy, I’ll present just one distinction within the presentation layer. DetailActivity hosts 2 fragments: ProfileDetailFragment to point out element of chosen profile and ChangePPFragment to edit chosen consumer’s profile image. These fragments are little one courses of CABDemoBaseFragment that implements CABSAPFragment. Let’s have a look at ProfileDetailFragment for example:
It has two buttons: Get Success and Get Fail. They name view mannequin’s getProfileDetail()
perform with parameters that obtained from arguments. Then observes the view mannequin’s profileDetailLiveData
. If it’s state is success, fills the display screen with the element information. Implementation of CABSAPFragment is defined in begin of this half.
This was half 3.
Pleased coding! 🎉
Half IV: