Android [ Java, Kotlin ]

[Android] Using Kotlin & MVVM Architecture

Moonsu99 2023. 7. 12. 10:05

[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]

Login Screen & Register Screen
Fragment

 

 

 

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.

Todo List's packages

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.