How to Use Huawei Cloud DB with Kotlin? Explained with a tutorial.
Implementation Cloud DB with livedata, recyclerview, viewmodel by using kotlin.
Hello everyone,
Welcome to article which will contain information and implemenation about Cloud DB. Here, we will build a sample application using Cloud DB from scratch.
Cloud DB is a product which provides to make synchronized data between cloud and client. The most important benefit which cloud DB provides is building serverless applications without requiring server deployment, operation, or maintenance. Additionally, It can be implemented in a few minutes.
Huawei Cloud DB is still in beta state. Until It is fully released, there may be some changes on informations in this article.
Preliminary Steps to Use Cloud DB
Before implementing Cloud DB, we need to complete preliminary steps.
- Have an account on Huawei Developer Console
- Create project on AGC (guide)
Lets create an application from scratch (empty activity)
After Cloud DB is enable for our project, lets add Cloud DB requirements to it.
- Add Cloud DB dependency to dependencies part of app level gradle.
implementation 'com.huawei.agconnect:agconnect-database:1.2.1.301'
- Add compileOptions options on app level gradle
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
We need to create Cloud DB Zone as first. What is Cloud DB Zone? A Cloud DB zone is an independent data storage zone. Multiple data Cloud DB zones are independent of each other. Each Cloud DB zone can store all object types whose versions are the latest. Lets create Cloud DB Zone on AGC Cloud DB. Enter AGC -> Cloud DB -> Cloud DB Zones
Now, We have a Cloud DB Zone which name is FoodDB. So, we can create our first ObjectType. We can think ObjectType as table in database. In our sample project, we will create two objecttypes which have one-to-many relationship. ObjectTypes are BaseFood and Ingredient.
Ingredient is the item which can be used in recipe (This includes information like; 3 * egg). BaseFood is the base food like egg. So, this is the logic between these two object types for project.
Then, we will export these object types and helper method. Click the export button in ObjectTypes field and choose java for file format (Cloud DB is not exporting files in kotlin, so we will use java in these part of project). Enter package name as like that (.remote is added to our main package name)
Now, we can go back to our project on android studio. Firstly, create package under main package directory.
In this directory (remote), lets add exported files. Exported files are BaseFood.java, Ingredient.java and helper class (ObjectTypeInfoHelper). Whenever we made some changes on ObjectTypes, this files should be updated. Because, It has version and object type informations.
There are some methods to use Cloud DB; opening, closing database, creating object types. We will use a class to handle these actions. So, lets create a kotlin class which name is CloudDbRepository. (We will add methods step by step. At the end of these steps, you can find the final class)
- Create a cloud db initialization method as companion object in class which takes context as parameter. This should be called when application is opened before cloud db processes are started.
companion object {
fun initAGConnectCloudDB(context: Context?) {
AGConnectCloudDB.initialize(context!!)
}
}
- Create an AGConnectCloudDB object in the class and initialize it in init method of this class. This object will be used to open cloud db zone (this is connection to cloud db)
class CloudDbRepository {
private var mCloudDb: AGConnectCloudDB init {
mCloudDb = AGConnectCloudDB.getInstance()
}}
- Create a CloudDbZone object which is initialized null. Then, lets create a method which name is openCloudDbZone. In this method, we will open cloud db zone. First parameter of CloudDBZoneConfig object is the name of db zone which we created.
var mCloudDbZone: CloudDBZone? = nullfun openCloudDbZone() {
val mConfig: CloudDBZoneConfig = CloudDBZoneConfig(
"FoodDB", CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC
)
mConfig.persistenceEnabled = true
try {
mCloudDbZone = mCloudDb.openCloudDBZone(mConfig, true)
} catch (exception: AGConnectCloudDBException) {
Log.w("CloudDbRepository", exception.errMsg)
}
}
We have some configs in this method as you see.
CLOUDDBZONE_CLOUD_CACHE option means cache mode which we use in our project. Data is stored on cloud. But It is cached on the device. After a listener is registered on the device to listen on the data on the cloud, the device is notified only when the data on the cloud changes. Other option to
CLOUDDBZONE_LOCAL_ONLY is another option to CloudDBZoneSyncProperty. This is local mode and Data is stored only on the device and is not synchronized to the cloud.
CloudDBZoneAccessProperty has only one option and it is CLOUDDBZONE_PUBLIC. It means public storage zone. Access is authenticated based on the user-defined permissions.
- Create a method which name is createObjectType. This method will create the object type with the help of helper method.
fun createObjectType(){
try {mCloudDb.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo())
} catch (exception: AGConnectCloudDBException){
Log.w("CloudDbRepository", exception.errMsg)
}
}
Now, CloudDbRepository class is ready to be used. This is the final state of CloudDbRepository:
ViewModel will be used to handle data interactions between app and Cloud DB. So, add the dependency below to app level gradle file dependencies;
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Then, create the MainActivityViewModel
class MainActivityViewModel : ViewModel() {
}
MainActivityViewModel should be called and connected to MainActivity.
private lateinit var viewModel: MainActivityViewModeloverride fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
}
In onCreate of MainActivity, initialization method for cloud db should be called. Because, Cloud DB is necessary to be initialized before any interaction in it.
class MainActivity : AppCompatActivity() { private lateinit var viewModel: MainActivityViewModel override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
CloudDbRepository.initAGConnectCloudDB(this)
viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
}
}
Then, we will write object type methods in seperate files. So, lets create another package as repository. Then create two class in this package; BaseFoodRepository and IngredientRepository.
According to scenerio in this project, we will list all basefoods. Whenever we click any base food, ingredients which includes clicked base food will be shown in a list. (Actually, this scenerio is made simple in a big project. So, getting implementation technics in this tutorial is the priority.)
An interface to be implemented in repositories can be created as followed
interface IRepository {
fun getAll()
fun getById(id: String)
}
BaseFoodRepository and IngredientRepository files:
In this two repository file, we have live data objects. As principal, they should not be observed directly from view. So, repository objects and similar LiveData objects are created in viewmodel.
By the way, we need create getAllBaseFood (which triggers to get data from cloud db in repository) and getIngredientByBaseFoodId (which triggers to get data by id filtering in repository) methods in viewmodel to be called in view.
Now, we need two adapters for recyclerviews. Lets implement adapters and layout of the items quickly. The parameters for them are MutableLiveData objects which get Basefood and Ingredient. AllBaseFoods data will be observed. Whenever it came, It will be shown in a recyclerview. Then, we are going to get filtered ingredient data. Also in here, It will be shown in another recyclerview. These are the reasong for adapters. Lets create another package which name is adapter. And add two adapters below in this package. Layout files can be created in layout resource folder.
To use recyclerview in project, a dependency to recyclerview should be added to app level gradle dependencies.
implementation "androidx.recyclerview:recyclerview:1.1.0"
Now, we should update activity_main.xml according to scenerio. Lets add a button which triggers to get all base food data. Then, two recyclerview elements should be written. After that, we are going to observe data from repository and show data in recyclerviews.
Lets go back to MainActivity. Firstly, we will add a clicklistener to get_all_base_foods_btn. Then, we need to observe live data objects from viewmodel to show data in recyclerviews. After that, we have last thing to do. It is click listener implementations in basefood adapter. In that click listener, we are going to get ingredient data with filter by base food id. Final MainActivity code is shown below.
//get all base food information from cloud db
get_all_base_foods_btn.setOnClickListener {
viewModel.getAllBaseFood()
}
To test our application, we need to add some dummy data on Cloud DB. Enter AGC -> Cloud DB -> Data Entries -> Choose Cloud DB Zone Name -> Enter BaseFood to object types input field -> Click ADD Button
Add multiple objects in here. Then, the same thing should be applied for Ingredient, too. But, there is a requirement for test in here. The basefoodid property of some ingredients should be equal to id of base food objects. Dont forget that id properties are primary keys. So, they should be unique values.
Add these dummy data to cloud db for test.
Dummy data for basefood;
id: 12315-21312-21312
name: Egg
calories: 75.0
carbohydrate: 0.5
protein: 7.0
fat: 5
measurementtype: 1id: 12231-2s213-12776
name: Yogurt
calories: 59.0
carbohydrate: 3.6
protein: 10.0
fat: 0.0
measurementtype: 1
Dummy data for ingredient;
id: 2134s-asdxd-32142
basefoodid: 12315-21312-21312
value: 3.0id: asd65-59526-45965
basefoodid: 12315-21312-21312
value: 2.0id: 12sxs-59999-85222
basefoodid: 12231-2s213-12776
value: 0.5
As you notice in data values, we connected basefood and ingredients. Now, lets run the application and see the result (In my project, I have so many basefood and ingredients — mock data. So, test results don’t include same number of samples.)
This sample project includes implementation Cloud DB and few features of it. There are many more features those can be used in Cloud DB. An also, we implemented it in a kind of repository pattern. All object types are writted in seperate parts. So, It is easy to handle data management.
By the way, dont forget that Cloud DB is still in beta version. So, this means that somethings may be changed until it is stable. Otherwise, features are going to be added in this period.
Please feel free to contact me in comments, if you have any concern or question. Or you can ask your Huawei Mobile Services related questions in Huawei developers forum: