[Android] Using Kotlin & MVVM Architecture
[Skills]
Languages | Kotlin |
Architecture | MVVM |
Jetpack | LiveData, DataBinding, ViewModel |
Local DB | SharedPreferences |
Image | Glide |
DI | Hilt |
Cloud Platform | FireBase |
[Implementation of this posting]
1. Create a project.
2. Connect to Firebase.
3. Login, registration page UI.
4. Implementing login and registration functions.
5. Create a fragment pages.
[Implementation screen]
1. Create a project(Empty Activity) MIN API-28.
2. Connecting to FireBase.
https://rivermoon99.tistory.com/14
[Android Kotlin Connecting to Firebase]
1. Access to Firebase.(https://firebase.google.com/) 2. Click "Get started" and Login 3. Click "Add project" Fill in the project name and click the Continue button.(Any project name is fine) Check "Enable Google Analytics for this project" and click the Co
rivermoon99.tistory.com
3. Configuring packages for MVVM architecture.
Data | |
api | Contains an API interface for communication with external services. For example, you can include an interface responsible for communicating with Firebase. |
model | Defines a data model class. For example, include the data structure of Todo entries. |
repository | It is responsible for interacting with data sources. For example, it manages communication with the Firebase Realtime Database and handles CRUD operations for data. |
Ui | |
base | Define a base class that contains the app's basic UI components or common logic. |
adapter | Contains the adapter class used to display lists, such as RecyclerView or ListView. |
view | Define screen elements, such as activities or fragments. Responsible for UI shown to users. |
viewmodel | Contains ViewModel classes. Acts as a mediator between View (Activity or Fragment) and Model |
utils | Contains utility classes or helper functions commonly used by applications. For example, you can implement features such as converting date formats and checking network status. |
4. create the Login page and the Register page UI.
[activity_login.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:backgroundTint="@color/white"
tools:context=".ui.main.view.LoginActivity">
<LinearLayout
android:layout_weight="3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="To Do List"
android:textSize="30sp"
android:textColor="@color/black"
android:fontFamily="@font/ths"/>
</LinearLayout>
<LinearLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/input_email"
android:background="@drawable/edit_radius_round"
android:layout_marginHorizontal="15dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="48dp"
android:fontFamily="@font/ths"
android:drawableStart="@drawable/baseline_perm_identity_24"
android:hint="Input E-Mail"/>
<EditText
android:id="@+id/input_password"
android:background="@drawable/edit_radius_round"
android:layout_marginHorizontal="15dp"
android:layout_width="match_parent"
android:layout_height="48dp"
android:fontFamily="@font/ths"
android:drawableStart="@drawable/baseline_password_24"
android:inputType="textPassword"
android:hint="Input Password"/>
<android.widget.Button
android:id="@+id/btn_Login"
android:layout_marginTop="20dp"
android:background="@drawable/login_button_clicked"
android:layout_marginHorizontal="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="Go Todo"/>
</LinearLayout>
<LinearLayout
android:layout_weight="1"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/go_Register"
android:gravity="center"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textColor="@color/black"
android:text="Register"
android:fontFamily="@font/ths"
android:textSize="15sp"/>
<TextView
android:gravity="center"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textColor="@color/black"
android:text="Forgot Password?"
android:fontFamily="@font/ths"
android:textSize="15sp"/>
</LinearLayout>
</LinearLayout>
[activity_register.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:backgroundTint="@color/white"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.main.view.RegisterActivity">
<LinearLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:orientation="vertical">
<ImageButton
android:id="@+id/back_btn"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/baseline_arrow_back_24"
android:background="@null"/>
<TextView
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="REGISTER"
android:textColor="@color/black"
android:fontFamily="@font/ths"
android:textSize="30sp"
android:gravity="center"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="E-Mail"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="15sp"/>
<EditText
android:id="@+id/edit_Email"
android:drawableStart="@drawable/baseline_email_24"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="15sp"
android:hint="Input E-Mail"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Password"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="15sp"/>
<EditText
android:id="@+id/edit_Password"
android:drawableStart="@drawable/baseline_password_24"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="15sp"
android:inputType="textPassword"
android:hint="Input Password"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Nickname"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="15sp"/>
<EditText
android:id="@+id/edit_Nickname"
android:drawableStart="@drawable/nickname_icon"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="15sp"
android:hint="Input Nickname"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Name"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="15sp"/>
<EditText
android:id="@+id/edit_Name"
android:drawableStart="@drawable/baseline_perm_identity_24"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="15sp"
android:hint="Input Name"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="bottom"
android:layout_marginBottom="20dp"
android:orientation="vertical">
<android.widget.Button
android:id="@+id/btn_Register"
android:background="@drawable/login_button_clicked"
android:layout_marginHorizontal="35dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="Register"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
5. Login and Registeration function implementation.
Now, Let's going to fill out the Kotlin file.
I think it's best to write it in the order of model → api → repository → viewmodel → ui → utils.
I can't write down all the codes, so I'll just describe them briefly. I will post the detailed code on GitHub.
The files for login and register are as follows.
Authapi.kt, FirebaseAuthapi.kt, User.kt, Authrepository.kt, LoginActivity.kt, RegisterActivity.kt, RegisterViewModel, InputValidator.kt
user.kt | data model class |
Authapi.kt | Includes an interface for interacting with Firebase Authentication. API call method definition related to membership |
AuthRepository.kt | this file is a repository class that interacts with the data sources associated with membership registration. Manage communications with Firebase Authentication and handle register logic. |
RegisterViewModel.kt | this file is a ViewModel class associated with the register screen. It acts as a mediator between View (Activity or Fragment) and Model (repository), processes user input, and executes register logic. |
6. Creating a fragment.
1. Create one HomeActivity(parent)
In HomeActivity, it consists of a navigation bar and a frame layout that can move fragments.
You should also create a menu file for navigation.
[menu.xml]
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Main"
android:id="@+id/home"
android:icon="@drawable/dashboard"/>
<item android:title="Cal"
android:id="@+id/calendar"
android:icon="@drawable/calendar"/>
<item android:title="Acc"
android:id="@+id/account_Book"
android:icon="@drawable/account"/>
<item android:title="CList"
android:id="@+id/check_List"
android:icon="@drawable/checklist"/>
</menu>
[activity_home.xml]
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_menu"
style="@style/BottomNavigationView">
</com.google.android.material.bottomnavigation.BottomNavigationView>
[HomeActivity.kt]
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
replaceFragment(HomeFragment())
window.statusBarColor = Color.parseColor("#000000")
binding.bottomNavigationView.setOnItemSelectedListener {
when(it.itemId){
R.id.home -> replaceFragment(HomeFragment())
R.id.calendar -> replaceFragment(CalendarFragment())
R.id.account_Book -> replaceFragment(AccountFragment())
R.id.check_List -> replaceFragment(CheckFragment())
else ->{
}
}
true
}
}
private fun replaceFragment(fragment: Fragment){
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.frame_layout,fragment)
fragmentTransaction.commit()
}
}
2. Right-click in layout directory → New → Fragment → Fragment(Blank)
The initial setup of the fragment does this.(Other fragments are the same.)
[HomeFragment.kt]
class HomeFragment : Fragment() {
lateinit var binding: FragmentHomeBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false)
// ActionBar hide
(activity as AppCompatActivity).supportActionBar?.hide()
return binding.root
}
}
That's the end of this post. The next post will be using the Google calendar API and overall UI configuration. Thanks.