top of page

Building a Product Listing and Addition App in Android with Kotlin, Retrofit, and Koin

Updated: Aug 17, 2023

Introduction:

In this blog post, we will create an Android app for product listing and addition. The app will allow users to view a list of products and add new products to the list. We'll use Kotlin as the primary programming language, Retrofit for API communication, and Koin for dependency injection. Additionally, we'll create RecyclerView adapters to display the product list and utilize ViewModel to manage the app's data and logic.


Prerequisites:

Before starting, make sure you have Android Studio installed and a basic understanding of Android app development and Kotlin programming.

  1. Setting Up the Project: Create a new Android project in Android Studio. For this tutorial, we'll name the app "DemoApp."

  2. Adding Required Dependencies: Open the app's build.gradle file and add the following dependencies:


// Retrofit and Gson
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"// Koin
implementation "org.koin:koin-androidx-viewmodel:3.1.2"// RecyclerView
implementation "androidx.recyclerview:recyclerview:1.2.1"

Sync the project after adding the dependencies.


Setting Up Koin: In the MainActivity, we'll set up Koin for dependency injection.


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        startKoin {
            androidLogger()
            androidContext(this@MainActivity)
            modules(appModule)
        }
    }
}

Creating the Data Model: Next, let's create a data model for the product. Create a new Kotlin file named "Product.kt" and add the following code:


data class Product(
    val id: String,
    val name: String,
    val type: String,
    val price: Double,
    val tax: Double,
    val imageUrl: String?
)

Defining the API Service: Create a new Kotlin file named "ProductService.kt" to define the Retrofit API service.



interface ProductService {
    @GET("public/get")suspend fun getProducts(): List<Product>

    @POST("public/add")@Multipartsuspend fun addProduct(
        @Part("product_name") productName: RequestBody,
        @Part("product_type") productType: RequestBody,
        @Part("price") price: RequestBody,
        @Part("tax") tax: RequestBody,
        @Part image: MultipartBody.Part?
    ): Response<ProductResponse>
}

Creating the Retrofit Client: Create a singleton object to initialize the Retrofit client in the "RetrofitService.kt" file:


object RetrofitService {
    private const val BASE_URL = "https://app.getswipe.in/api/"

    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val productService: ProductService = retrofit.create(ProductService::class.java)
}

Creating the Repository: Create a repository class named "ProductRepository.kt" to handle data operations.



class ProductRepository(private val productService: ProductService) {
    suspend fun getProducts(): List<Product> {
        return productService.getProducts()
    }

    suspend fun addProduct(
        productName: String,
        productType: String,
        price: String,
        tax: String,
        imageFile: MultipartBody.Part? = null
    ): Result<ProductResponse> {
        try {
            val productNameBody = createRequestBody(productName)
            val productTypeBody = createRequestBody(productType)
            val priceBody = createRequestBody(price)
            val taxBody = createRequestBody(tax)


            val response = productService.addProduct(productNameBody, productTypeBody, priceBody, taxBody, imageFile)

            if (response.isSuccessful) {
                response.body()?.let {
                    return Result.success(it)
                } ?: run {
                    return Result.failure(java.lang.Exception("On failed"))
                }
            } else {
                return Result.failure(java.lang.Exception("Failed to add product. Please try again."))
            }
        } catch (e: Exception) {
            return Result.failure(java.lang.Exception("An error occurred. Please try again."))
        }
    }

    private fun createRequestBody(value: String): RequestBody {
        return RequestBody.create(okhttp3.MultipartBody.FORM, value)
    }
}
                                                                                                    

Designing the Layouts: Create the layout files for the activity and product item. In the "activity_main.xml" file, add the following layout:


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

                                                                                                    


<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="product"
            type="com.example.demoapp.listing.Product" />
    </data>

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:padding="16dp">

        <!-- Your desired layout for the item -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <!-- User Profile Section -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="center_vertical">

                <!-- User Profile Image -->
                <ImageView
                    android:id="@+id/userProfileImage"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:src="@drawable/user_profile_image"
                    android:scaleType="centerCrop"
                    android:layout_marginEnd="8dp" />

                <!-- User Name -->
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Username"
                    android:textSize="16sp"
                    android:textStyle="bold"
                    android:textColor="@android:color/black" />

            </LinearLayout>

            <!-- Product Image -->
            <ImageView
                android:id="@+id/productImage"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="centerCrop"
                android:src="@drawable/ic_launcher_background" />

            <!-- Divider -->
            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/dividerColor"
                android:layout_marginTop="6dp"
                android:layout_marginBottom="6dp" />

            <!-- Product Name -->
            <TextView
                android:id="@+id/productName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{product.product_name}"
                android:textSize="18sp"
                android:textStyle="bold"
                android:textColor="@android:color/black"
                android:paddingTop="2dp" />

            <!-- Product Type -->
            <TextView
                android:id="@+id/productType"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{product.product_type}"
                android:textSize="14sp"
                android:textColor="@android:color/darker_gray"
                android:paddingTop="2dp" />

            <!-- Price and Tax -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:paddingTop="4dp">

                <TextView
                    android:id="@+id/price"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{String.format(`$%.2f`, product.price)}"
                    android:textSize="16sp"
                    android:textStyle="bold"
                    android:textColor="@color/black" />

                <TextView
                    android:id="@+id/tax"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="8dp"
                    android:text="@{String.format(`Tax: %.1f%%`, product.tax)}"
                    android:textSize="14sp"
                    android:textColor="@android:color/darker_gray" />

            </LinearLayout>

            <!-- Like and Comment Icons -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="end"
                android:paddingTop="4dp">

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:src="@drawable/ic_like"
                    android:layout_marginEnd="8dp" />

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:src="@drawable/ic_comment" />

            </LinearLayout>

        </LinearLayout>
    </androidx.cardview.widget.CardView>
</layout>

Output:


Conclusion:

In conclusion, we have successfully developed an Android app for product listing and addition using Kotlin, Retrofit, and Koin. Throughout the process, we learned how to set up the project, handle API communication with Retrofit, manage dependencies with Koin, and implement RecyclerView adapters to display the product list.

By leveraging Kotlin's concise syntax and powerful features, we were able to create a clean and maintainable codebase for our app. The ViewModel architecture allowed us to separate the app's data and business logic from the UI, ensuring a more organized and scalable application.

Furthermore, the use of Retrofit facilitated smooth communication with the backend API, allowing us to fetch and display the product data seamlessly.

The Koin library simplified the dependency injection process, making it easier to manage and access our app's components.

Although we built a basic product listing and addition app, this project can be extended and customized according to specific requirements.

For instance, we can add features like product editing, deletion, and user authentication to create a more robust and user-friendly application.

Overall, this blog post provided a step-by-step guide to developing an Android app with Kotlin, Retrofit, and Koin, demonstrating the power and flexibility of these technologies in modern app development.

As you continue your journey in Android app development, feel free to explore more advanced concepts and best practices to create even more sophisticated and feature-rich applications. Happy coding!


Whether you need assistance with Android app development, UI/UX design, debugging, or any other aspect of Android programming, our experts are ready to provide you with tailored solutions. We cover a wide range of topics, including Android architecture, Kotlin programming, database integration, API integration, and more.




Why choose CodersArts?



  1. Expert Assistance: Our team consists of highly skilled Android developers who have extensive experience in the field. They are proficient in the latest tools, frameworks, and technologies, ensuring top-notch solutions for your assignments.

  2. Timely Delivery: We understand the importance of deadlines. Our experts work diligently to deliver your completed assignments on time, allowing you to submit your work without any worries.

  3. Customized Solutions: We believe in providing personalized solutions that meet your specific requirements. Our experts carefully analyze your assignment and provide tailored solutions to ensure your success.

  4. Affordable Pricing: We offer competitive and affordable pricing to make our services accessible to students. We understand the financial constraints that students often face, and our pricing is designed to accommodate their needs.

  5. 24/7 Support: Our customer care team is available round the clock to assist you with any queries or concerns you may have. You can reach us via phone, email, or live chat.

Contact CodersArts today for reliable and professional Android assignment help. Let our experts take your Android programming skills to the next level!




bottom of page