在本文中,我们将使用android studio在android中构建杂货店应用程序。很多时候,我们忘记购买要购买的东西,毕竟我们忘记了所有物品,因此,借助此应用程序,您可以记下要购买的杂货您不会忘记要购买的任何物品。下面给出了一个示例图像,以使您对本文中要做的事情有一个了解。请注意,我们将使用Kotlin语言实施此项目。
在此项目中,我们将MVVM(模型视图ViewModel)用于建筑模式,将Room用于数据库,协程和RecyclerView用于显示项目列表。在跳到项目之前,让我们了解这些术语。
MVVM(模型视图ViewModel)
android中的MVVM体系结构用于为项目的代码提供结构并轻松理解代码。 MVVM是Android中的架构设计模式。 MVVM将Activity类和XML文件视为View。这种设计模式将UI与逻辑完全分开。这是快速了解MVVM的图像。
看完该图像后,如果您不了解其工作原理,请不要担心,因为我们将编写完全理解的代码。
ROOM数据库
Room Persistence库是一个数据库管理库,用于存储诸如杂货项目名称,杂货项目数量和杂货价格等应用程序的数据。 Room是SQLite的覆盖层,可帮助轻松地对数据库执行操作。
回收站
RecyclerView是一个容器,用于显示大量数据集中的数据集合,可以通过维护有限数量的视图来非常有效地滚动数据集。
协程
协程是轻量级线程,我们使用协程对其他线程执行操作,因此,我们的主线程不会阻塞,并且我们的应用程序不会崩溃。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Kotlin作为编程语言。
第2步:首先进入编码部分,您必须做一些准备工作
在进行编码之前,首先将这些库添加到gradle文件中,然后将插件应用为“ kotlin-kapt”。要添加这些库,请转到Gradle脚本> build.gradle(Module:app)。
def room_version = “2.2.1”
def lifecycle_version = “2.0.0”
// Room and Architectural Components
implementation “androidx.room:room-runtime:$room_version”
implementation “androidx.legacy:legacy-support-v4:1.0.0”
implementation ‘androidx.lifecycle:lifecycle-extensions:2.1.0’
implementation ‘androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0’
implementation “androidx.room:room-ktx:2.2.1”
kapt “androidx.room:room-compiler:$room_version”
// Coroutines
implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0’
implementation “org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0”
// New Material Design
implementation “com.google.android.material:material:1.0.0”
// ViewModel
implementation “androidx.lifecycle:lifecycle-extensions:$lifecycle_version”
implementation “androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version”
kapt “androidx.lifecycle:lifecycle-compiler:$lifecycle_version”
以下是build.gradle(:app)文件的完整代码。
Kotlin
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.grocerylist"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
def room_version = "2.2.1"
def lifecycle_version = "2.0.0"
// Room and Architectural Components
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
implementation "androidx.room:room-ktx:2.2.1"
kapt "androidx.room:room-compiler:$room_version"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
// New Material Design
implementation "com.google.android.material:material:1.0.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
}
XML
Fresh Basket
Hello blank fragment
Banana
35
250Rs
20
Total Cost
Add Items to your cart
Item
Quantity
Price
Save
Cancel
XML
#0AD042
#03551A
#03DAC5
#000000
#ffffff
Kotlin
package com.example.grocerylist.Database.Entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
// This is a data class which store data.
// Entities class create a table in database,
// in our database we will create three column
@Entity(tableName = "grocery_items")
data class GroceryItems(
// create itemName variable to
// store grocery items.
@ColumnInfo(name = "itemName")
var itemName: String,
// create itemQuantity variable
// to store grocery quantity.
@ColumnInfo(name = "itemQuantity")
var itemQuantity: Int,
// create itemPrice variable to
// store grocery price.
@ColumnInfo(name = "itemPrice")
var itemPrice: Int
) {
// Primary key is a unique key
// for different database.
@PrimaryKey(autoGenerate = true)
var id: Int? = null
}
Kotlin
package com.example.grocerylist.Database
import androidx.lifecycle.LiveData
import androidx.room.*
import com.example.grocerylist.Database.Entity.GroceryItems
// This class is used to create
// function for database.
@Dao
interface GroceryDao {
// Insert function is used to
// insert data in database.
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(item: GroceryItems)
// Delete function is used to
// delete data in database.
@Delete
suspend fun delete(item: GroceryItems)
// getAllGroceryItems function is used to get
// all the data of database.
@Query("SELECT * FROM grocery_items")
fun getAllGroceryItems(): LiveData>
}
Kotlin
package com.example.grocerylist.Database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.grocerylist.Database.Entity.GroceryItems
@Database(entities = [GroceryItems::class], version = 1)
abstract class GroceryDatabase : RoomDatabase() {
abstract fun getGroceryDao(): GroceryDao
companion object {
@Volatile
private var instance: GroceryDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: createDatabase(context).also {
instance = it
}
}
private fun createDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext, GroceryDatabase::class.java, "GroceryDatabase.db").build()
}
}
Kotlin
package com.example.grocerylist.Database
import com.example.grocerylist.Database.Entity.GroceryItems
class GroceryRepository(private val db: GroceryDatabase) {
suspend fun insert(item: GroceryItems) = db.getGroceryDao().insert(item)
suspend fun delete(item: GroceryItems) = db.getGroceryDao().delete(item)
fun allGroceryItems() = db.getGroceryDao().getAllGroceryItems()
}
Kotlin
package com.example.grocerylist.UI
import androidx.lifecycle.ViewModel
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryRepository
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class GroceryViewModel(private val repository: GroceryRepository) : ViewModel() {
// In coroutines thread insert item in insert function.
fun insert(item: GroceryItems) = GlobalScope.launch {
repository.insert(item)
}
// In coroutines thread delete item in delete function.
fun delete(item: GroceryItems) = GlobalScope.launch {
repository.delete(item)
}
//Here we initialized allGroceryItems function with repository
fun allGroceryItems() = repository.allGroceryItems()
}
Kotlin
package com.example.grocerylist.UI
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.grocerylist.Database.GroceryRepository
class GroceryViewModelFactory(private val repository: GroceryRepository):ViewModelProvider.NewInstanceFactory() {
override fun create(modelClass: Class): T {
return GroceryViewModel(repository) as T
}
}
XML
XML
Kotlin
package com.example.grocerylist.Adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import com.example.grocerylist.UI.GroceryViewModel
import kotlinx.android.synthetic.main.groceryadapter.view.*
class GroceryAdapter(var list: List, val viewModel: GroceryViewModel) :
RecyclerView.Adapter() {
// In this function we will add our groceryadapter.xml to kotlin class
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroceryViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.groceryadapter, parent, false)
return GroceryViewHolder(view)
}
// This function is used to return total number of size of list.
override fun getItemCount(): Int {
return list.size
}
// In onBindViewHolder we will bind our itemViews with adapter
override fun onBindViewHolder(holder: GroceryViewHolder, position: Int) {
var currentPosition = list[position]
holder.itemView.txtItemName.text = currentPosition.itemName
holder.itemView.txtItemPrice.text = "${currentPosition.itemPrice}"
holder.itemView.txtItemQuantity.text = "${currentPosition.itemQuantity}"
holder.itemView.ibDelete.setOnClickListener {
viewModel.delete(currentPosition)
}
// To get total cost
if (position == list.size - 1) {
var totalCost = 0
for (i in 0 until list.size) {
totalCost += list[i].itemPrice
}
holder.itemView.txtItemTotalCost.visibility = View.VISIBLE
holder.itemView.txtTotalCostTitle.visibility = View.VISIBLE
holder.itemView.txtItemTotalCost.text = "$totalCost"
}
}
// Inner class for viewHolder
inner class GroceryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
XML
Kotlin
package com.example.grocerylist.UI
import com.example.grocerylist.Database.Entity.GroceryItems
interface DialogListener {
// Create a function to add items
// in GroceryItems on clicking
fun onAddButtonClicked(item:GroceryItems)
}
Kotlin
package com.example.grocerylist.UI
import android.content.Context
import android.os.Bundle
import android.view.Window
import android.widget.Toast
import androidx.appcompat.app.AppCompatDialog
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.grocerydialog.*
class GroceryItemDialog(context: Context, var dialogListener: DialogListener) : AppCompatDialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.grocerydialog)
// Click listener on Save button
// to save all data.
tvSave.setOnClickListener {
// Take all three inputs in different variables from user
// and add it in Grocery Items database
val name = etItemName.text.toString()
val quantity = etItemQuantity.text.toString().toInt()
val price = etItemPrice.text.toString().toInt()
// Toast to display enter items in edit text
if (name.isEmpty()) {
Toast.makeText(context, "Please Enter Item Name", Toast.LENGTH_SHORT).show()
}
val item = GroceryItems(name, quantity, price)
dialogListener.onAddButtonClicked(item)
dismiss()
}
// On click listener on cancel text to close dialog box
tvCancel.setOnClickListener {
cancel()
}
}
}
Kotlin
package com.example.grocerylist.UI
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.grocerylist.Adapter.GroceryAdapter
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryDatabase
import com.example.grocerylist.Database.GroceryRepository
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
lateinit var ViewModel: GroceryViewModel
lateinit var list: List
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val groceryRepository = GroceryRepository(GroceryDatabase(this))
val factory = GroceryViewModelFactory(groceryRepository)
// Initialised View Model
ViewModel = ViewModelProvider(this, factory).get(GroceryViewModel::class.java)
val groceryAdapter = GroceryAdapter(listOf(), ViewModel)
rvList.layoutManager = LinearLayoutManager(this)
rvList.adapter = groceryAdapter
// To display all items in recycler view
ViewModel.allGroceryItems().observe(this, Observer {
groceryAdapter.list = it
groceryAdapter.notifyDataSetChanged()
})
// on ClickListener on button to open dialog box
btnAdd.setOnClickListener {
GroceryItemDialog(this, object : DialogListener {
override fun onAddButtonClicked(item: GroceryItems) {
ViewModel.insert(item)
}
}).show()
}
}
}
以下是字符串.xml文件的代码。在这里,我们添加了将在项目中使用的必要字符串。
XML格式
Fresh Basket
Hello blank fragment
Banana
35
250Rs
20
Total Cost
Add Items to your cart
Item
Quantity
Price
Save
Cancel
以下是colors.xml文件的代码。在这里,我们添加了将在项目中使用的必要颜色。
XML格式
#0AD042
#03551A
#03DAC5
#000000
#ffffff
步骤3:建立会议室资料库
a)实体类
实体类包含数据库中的所有列,并应使用@Entity(tablename =“表名”)进行注释。实体类是数据类。 @Column info批注用于输入列变量名称和数据类型。我们还将添加自动增加的主键。转到应用> Java > com.example.application-name。右键单击com.example.application-name,然后转到new并创建Kotlin文件/类,然后将该文件命名为GroceryEntities 。 请参阅下面的代码以完全理解和实现。
科特林
package com.example.grocerylist.Database.Entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
// This is a data class which store data.
// Entities class create a table in database,
// in our database we will create three column
@Entity(tableName = "grocery_items")
data class GroceryItems(
// create itemName variable to
// store grocery items.
@ColumnInfo(name = "itemName")
var itemName: String,
// create itemQuantity variable
// to store grocery quantity.
@ColumnInfo(name = "itemQuantity")
var itemQuantity: Int,
// create itemPrice variable to
// store grocery price.
@ColumnInfo(name = "itemPrice")
var itemPrice: Int
) {
// Primary key is a unique key
// for different database.
@PrimaryKey(autoGenerate = true)
var id: Int? = null
}
b)道接口
Dao是一个接口,我们可以在其中创建要在数据库上实现的所有功能。该接口还用@Dao注释。现在,我们将使用暂停功能创建一个函数,该函数是协程函数。在这里,我们创建了三个函数,第一个是用于在数据库中插入项目并用@Insert注释的插入函数,第二个是用于从数据库中用@Delete注释的项删除项目,第三个是使用@Query注释的所有项。转到应用> Java > com.example.application-name 。右键单击com.example.application-name,然后转到new并创建Kotlin文件/类,并将该文件命名为GroceryDao 。请参见下面的代码以实现。
科特林
package com.example.grocerylist.Database
import androidx.lifecycle.LiveData
import androidx.room.*
import com.example.grocerylist.Database.Entity.GroceryItems
// This class is used to create
// function for database.
@Dao
interface GroceryDao {
// Insert function is used to
// insert data in database.
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(item: GroceryItems)
// Delete function is used to
// delete data in database.
@Delete
suspend fun delete(item: GroceryItems)
// getAllGroceryItems function is used to get
// all the data of database.
@Query("SELECT * FROM grocery_items")
fun getAllGroceryItems(): LiveData>
}
c)数据库类
用@Database注释的数据库类(实体= [Entity class.class的名称],版本= 1)这些实体是实体数组列表,列出了与数据库相关联的所有数据实体,并且版本显示了数据库的当前版本。该数据库类继承自Room Database类。在GroceryDatabase类中,我们将提供一个抽象方法来获取DAO的实例,并进一步使用DAO实例中的此方法与数据库进行交互。请参见下面的代码来实现。去 应用> Java > com.example.application-name 。右键单击com.example.application-name,然后转到new并将Kotlin文件/类创建为GroceryDatabase 。请参见下面的代码以实现。
科特林
package com.example.grocerylist.Database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.grocerylist.Database.Entity.GroceryItems
@Database(entities = [GroceryItems::class], version = 1)
abstract class GroceryDatabase : RoomDatabase() {
abstract fun getGroceryDao(): GroceryDao
companion object {
@Volatile
private var instance: GroceryDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: createDatabase(context).also {
instance = it
}
}
private fun createDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext, GroceryDatabase::class.java, "GroceryDatabase.db").build()
}
}
步骤4:现在,我们将在应用程序中实现架构结构
a)储存库类
知识库是设计结构之一。存储库类将数据提供给ViewModel类,然后ViewModel类将该数据用于View。存储库将在本地或网络上选择适当的数据。在这里,在我们的Grocery Repository类中,数据是从Room数据库本地获取的。我们将通过创建数据库实例并将其存储在Grocery Repository类的db变量中来添加构造函数值。去 应用> Java > com.example.application-name 。右键单击com.example.application-name,然后转到new并将Kotlin文件/类创建为GroceryRepository 。请参见下面的代码以实现。
科特林
package com.example.grocerylist.Database
import com.example.grocerylist.Database.Entity.GroceryItems
class GroceryRepository(private val db: GroceryDatabase) {
suspend fun insert(item: GroceryItems) = db.getGroceryDao().insert(item)
suspend fun delete(item: GroceryItems) = db.getGroceryDao().delete(item)
fun allGroceryItems() = db.getGroceryDao().getAllGroceryItems()
}
转到应用程序> Java > com.example.application-name 。右键单击com.example.application-name,转到new并创建一个名为UI的新程序包,然后右键单击UI程序包并创建Kotlin文件/类。请参见下面的代码以实现。
b)ViewModel类
ViewModel类用作View和Data之间的接口。杂货店View模型类继承自View模型类,我们将通过创建Repository类的实例变量并将其存储在存储库变量中来传递构造函数值。当我们在View Model中传递构造函数时,我们必须创建另一个类,即Factory View Model类。转到应用程序> Java > com.example.application-name> UI 。右键单击UI包,然后创建Kotlin文件/类,然后将该文件命名为GroceryViewModel 。请参见下面的代码。
科特林
package com.example.grocerylist.UI
import androidx.lifecycle.ViewModel
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryRepository
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class GroceryViewModel(private val repository: GroceryRepository) : ViewModel() {
// In coroutines thread insert item in insert function.
fun insert(item: GroceryItems) = GlobalScope.launch {
repository.insert(item)
}
// In coroutines thread delete item in delete function.
fun delete(item: GroceryItems) = GlobalScope.launch {
repository.delete(item)
}
//Here we initialized allGroceryItems function with repository
fun allGroceryItems() = repository.allGroceryItems()
}
c)工厂ViewModel类
我们将从ViewModelProvider.NewInstanceFactory继承Grocery ViewModel Factory类,并通过创建Grocery Repository的实例变量来再次传递构造函数值,并返回GroceryViewModel(respository)。转到应用> Java > com.example.application-name> UI 。右键点击 UI包,并创建一个名为GroceryViewModelFactory的Kotlin文件/类。请参阅下面的代码以了解。
科特林
package com.example.grocerylist.UI
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.grocerylist.Database.GroceryRepository
class GroceryViewModelFactory(private val repository: GroceryRepository):ViewModelProvider.NewInstanceFactory() {
override fun create(modelClass: Class): T {
return GroceryViewModel(repository) as T
}
}
第5步:现在,让我们进入UI部分
在activity_main.xml中的文件,我们会点击这个按钮对话框打开后添加两个ImageView的,RecyclerView和按钮,在对话框中用户可以输入项目名称,项目数量和项目价格。请参考以下代码。
XML格式
XML代码的输出:
第6步:让我们实现RecyclerView 。现在,我们将对列表中行的UI部分进行编码。转到应用程序> res>布局。右键单击布局,转到“新建”,然后添加一个布局资源文件并将其命名为食品杂货店。请参阅groceradaptapt.xml文件的XML代码。
XML格式
XML代码的输出:
我们将为回收者视图编码适配器类。在Grocery Adapter类中,我们将通过将实体类作为列表存储在list变量中来添加构造函数值,并创建视图模型的实例。在Grocery Adapter中,我们将覆盖三个函数:onCreateViewHolder,getItemCount和onbindViewHolder,我们还将创建一个称为杂货店视图持有人的内部类。转到应用> Java > com.example.application-name 。右键单击com.example.application-name转到new并创建一个名为Adapter的新程序包,然后右键单击Adapter程序包并创建一个名为GroceryAdapter的Kotlin文件/类。请参见下面的代码。
科特林
package com.example.grocerylist.Adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import com.example.grocerylist.UI.GroceryViewModel
import kotlinx.android.synthetic.main.groceryadapter.view.*
class GroceryAdapter(var list: List, val viewModel: GroceryViewModel) :
RecyclerView.Adapter() {
// In this function we will add our groceryadapter.xml to kotlin class
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroceryViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.groceryadapter, parent, false)
return GroceryViewHolder(view)
}
// This function is used to return total number of size of list.
override fun getItemCount(): Int {
return list.size
}
// In onBindViewHolder we will bind our itemViews with adapter
override fun onBindViewHolder(holder: GroceryViewHolder, position: Int) {
var currentPosition = list[position]
holder.itemView.txtItemName.text = currentPosition.itemName
holder.itemView.txtItemPrice.text = "${currentPosition.itemPrice}"
holder.itemView.txtItemQuantity.text = "${currentPosition.itemQuantity}"
holder.itemView.ibDelete.setOnClickListener {
viewModel.delete(currentPosition)
}
// To get total cost
if (position == list.size - 1) {
var totalCost = 0
for (i in 0 until list.size) {
totalCost += list[i].itemPrice
}
holder.itemView.txtItemTotalCost.visibility = View.VISIBLE
holder.itemView.txtTotalCostTitle.visibility = View.VISIBLE
holder.itemView.txtItemTotalCost.text = "$totalCost"
}
}
// Inner class for viewHolder
inner class GroceryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
步骤7:要从用户输入杂货项目,数量和价格,我们必须创建一个界面。为了实现此接口,我们将使用DialogBox。首先创建对话框的UI。在此对话框中,我们将添加三个编辑文本和两个文本视图。三个编辑文本可输入食品杂货的名称,数量和价格。两种文本视图,一种用于保存,另一种用于取消。单击保存文本后,所有保存到数据库的数据都将被保存,并通过单击“取消文本”对话框关闭。转到应用程序> res>布局。右键单击布局,转到“新建”,然后添加一个“布局资源文件”,并将其命名为“杂货店对话框” 。请参阅杂货店dialog.xml文件的XML代码。
XML格式
XML代码的输出:
要在保存文本上添加clicklistener,我们必须首先创建一个接口,然后在其中创建一个函数。去 应用> Java > com.example.application-name> UI。右键点击 UI包并创建Kotlin文件/类,并创建一个名为DialogListener的接口。请参阅DialogListener.kt文件的代码。
科特林
package com.example.grocerylist.UI
import com.example.grocerylist.Database.Entity.GroceryItems
interface DialogListener {
// Create a function to add items
// in GroceryItems on clicking
fun onAddButtonClicked(item:GroceryItems)
}
现在,我们将创建食品杂货对话框类,在其中将所有输入保存在不同的变量中,然后插入数据库中。转到应用> Java > com.example.application-name> UI。右键单击UI包,创建一个Kotlin文件/类,并创建一个名为GroceryItemDialog的类。请参见下面的代码。
科特林
package com.example.grocerylist.UI
import android.content.Context
import android.os.Bundle
import android.view.Window
import android.widget.Toast
import androidx.appcompat.app.AppCompatDialog
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.grocerydialog.*
class GroceryItemDialog(context: Context, var dialogListener: DialogListener) : AppCompatDialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.grocerydialog)
// Click listener on Save button
// to save all data.
tvSave.setOnClickListener {
// Take all three inputs in different variables from user
// and add it in Grocery Items database
val name = etItemName.text.toString()
val quantity = etItemQuantity.text.toString().toInt()
val price = etItemPrice.text.toString().toInt()
// Toast to display enter items in edit text
if (name.isEmpty()) {
Toast.makeText(context, "Please Enter Item Name", Toast.LENGTH_SHORT).show()
}
val item = GroceryItems(name, quantity, price)
dialogListener.onAddButtonClicked(item)
dismiss()
}
// On click listener on cancel text to close dialog box
tvCancel.setOnClickListener {
cancel()
}
}
}
步骤8:最后,在这一步中,我们将在MainActivity中进行编码。在我们的主要活动中,我们必须设置回收站视图,并在添加按钮上添加单击侦听器以打开对话框。转到MainActivity.kt文件,并参考以下代码。下面是MainActivity.kt文件的代码。在代码内部添加了注释,以更详细地了解代码。
科特林
package com.example.grocerylist.UI
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.grocerylist.Adapter.GroceryAdapter
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryDatabase
import com.example.grocerylist.Database.GroceryRepository
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
lateinit var ViewModel: GroceryViewModel
lateinit var list: List
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val groceryRepository = GroceryRepository(GroceryDatabase(this))
val factory = GroceryViewModelFactory(groceryRepository)
// Initialised View Model
ViewModel = ViewModelProvider(this, factory).get(GroceryViewModel::class.java)
val groceryAdapter = GroceryAdapter(listOf(), ViewModel)
rvList.layoutManager = LinearLayoutManager(this)
rvList.adapter = groceryAdapter
// To display all items in recycler view
ViewModel.allGroceryItems().observe(this, Observer {
groceryAdapter.list = it
groceryAdapter.notifyDataSetChanged()
})
// on ClickListener on button to open dialog box
btnAdd.setOnClickListener {
GroceryItemDialog(this, object : DialogListener {
override fun onAddButtonClicked(item: GroceryItems) {
ViewModel.insert(item)
}
}).show()
}
}
}
这就是完整的项目结构。
输出:
Github链接: https : //github.com/arpit-288/Fresh_Basket