Seting a Query in Firestore Cloud - kotlin

I have a question becouse i wrote this with a guide and it displays me all of the documents and i wanna that it displays only this with one i login in to my app and its will be nice when this wil be in 1 line and no i 2 seperates but it is not so necessary
val imie="Sebastian"
val query = db.collection("users").whereEqualTo("welcome",imie).orderBy("displayName")
val options = FirestoreRecyclerOptions.Builder<User>().setQuery(query, User::class.java)
.setLifecycleOwner(this).build()
val adapter = object: FirestoreRecyclerAdapter<User, UserViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(this#MainActivity).inflate(android.R.layout.simple_list_item_2,parent,false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: User) {
val tvWelcome: TextView=holder.itemView.findViewById(android.R.id.text1)
val tvName: TextView=holder.itemView.findViewById(android.R.id.text2)
tvWelcome.text = model.welcome
tvWelcome.text = model.displayName
tvName.text = model.displayName
}
}
val uzytkownik: RecyclerView = findViewById(R.id.uzytkownik)
uzytkownik.adapter = adapter
uzytkownik.layoutManager = LinearLayoutManager(this)
Firebase console

val query = db.collection("users").whereEquelTo("firebasefieldName",youvalue)
Youvalue will write the data of the person you want to see.
eg:"Sebastian"
firebasefieldName will be your domain name in firebase
eg:displayName
Additional Information:
db.collection("users").whereEquelTo("fieldName1",youvalue).orderBy("fieldName2")
lists the listing in descending order of equal value
but after doing that you will get an error message there will be a link to that error message go to it and confirm everything.
Please support if it worked.

In this way, the data is updated instantly, for example, add a data to the table and it will appear in the list directly.
You can adjust it yourself.
Looks like I can't help any other way either. Will you still vote for me?
fun realtimeList(
collectionPath: String,
context: Context,
cevapField: String,
cevapdurum: Boolean,
field: String,
equel: String,
query: Query.Direction
): LiveData<MutableList<Any>> {
val mutableData = MutableLiveData<MutableList<Any>>()
val docRef = Firebase.firestore.collection(collectionPath)
docRef
.whereEqualTo(field, equel)
.whereEqualTo(cevapField, cevapdurum)
.orderBy("date", query)
.addSnapshotListener { querySnapshot, firebaseFirestoreException ->
firebaseFirestoreException?.let {
context.showShortToast(it.message.toString())
return#addSnapshotListener
}
val listData: MutableList<Any> = mutableListOf()
querySnapshot?.let {
for (document in it) {
val polyclinic = document.getString("policinic")
val title = document.getString("title")
val description = document.getString("descripiton")
val date: Long = document.get("date") as Long
val userid = document.getString("userid")
val quetinid = document.id
val cevapDurum = document.get("cevapdurum")
val questionio =
Questionio(
polyclinic!!,
title!!,
description!!,
SimpleDateFormat(date, "dd MMMM yyyy"),
SimpleDateFormat(date, "HH:mm"),
userid!!,
quetinid,
cevapDurum as Boolean
)
listData.add(questionio)
}
mutableData.value = listData
}
}
return mutableData
}
Part of my list adapter class
inner class ListViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun bindView(questionio: Questionio) {
itemView.findViewById<TextView>(R.id.txt_policlinic).text = questionio.policlinic
itemView.findViewById<TextView>(R.id.txt_title).text = questionio.title
itemView.findViewById<TextView>(R.id.txt_description).text = questionio.description
itemView.findViewById<TextView>(R.id.txt_date).text = questionio.date
itemView.findViewById<TextView>(R.id.txt_time).text = questionio.time
val txtCevapDurum = itemView.findViewById<TextView>(R.id.txt_CevapDurum)
if (questionio.cevapdurum == true) {
txtCevapDurum.setText(R.string.answered)
txtCevapDurum.setTextColor(Color.GREEN)
} else {
txtCevapDurum.setText(R.string.not_answered)
txtCevapDurum.setTextColor(Color.RED)
}
}
init {
itemView.setOnClickListener {
listener.onItemClick(adapterPosition)
}
}
}
videos
https://www.youtube.com/watch?v=TIub9JMYhDs&t=226s&ab_channel=PhilippLackner
https://www.youtube.com/watch?v=Lfum5cO8LHA&ab_channel=SociedadAndroide

Related

How do I take data from a firebase database and show it in a recycler view?

Im trying to get data from a firebase database collection and show it in a recycler view.
My collection is called savedDailyPlan. I am super new to kotlin and to android studio and I'm having a hard time finding the solution to this problem.
This is my data class:
data class DoneExercise(
var exerciseName : String = "",
var weight : Int = 0,
var sets : Int = 0,
var reps : Int = 0,
var date : Timestamp = Timestamp.now()
)
This is my adapter:
class DailyWorkoutAdapter(private val items: List<DoneExercise>) : RecyclerView.Adapter<DailyWorkoutAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.plan_list_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
holder.property1.text = item.exerciseName
holder.property2.text = item.weight.toString()
//holder.property3.text = item.sets.toString()
//holder.property4.text = item.reps.toString()
}
override fun getItemCount(): Int = items.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val property1: TextView = itemView.findViewById(R.id.tv_day_name)
val property2: TextView = itemView.findViewById(R.id.tv_exercise_name)
//val property3: TextView = itemView.findViewById(R.id.property3)
//val property4: TextView = itemView.findViewById(R.id.property4)
}
}
I tried this but nothing shows up after i press the Positive Button:
private fun showPlanDialog() {
val db = FirebaseFirestore.getInstance()
val collectionRef = db.collection("savedDailyPlan")
val showDailyWorkoutHelper = LayoutInflater.from(context).inflate(R.layout.show_daily_exercises, null)
val dialogHelperDaily= ShowDailyWorkoutHelper(showDailyWorkoutHelper)
AlertDialog.Builder(context)
.setView(showDailyWorkoutHelper)
.setTitle("Generate plan")
.setPositiveButton("Choose day") {_, _ ->
recyclerView.layoutManager = LinearLayoutManager(context)
val dailyWorkoutsList: MutableList<DoneExercise> = arrayListOf()
val dailyWorkoutAdapter = DailyWorkoutAdapter(dailyWorkoutsList)
recyclerView.adapter = dailyWorkoutAdapter
}.show()
}
The Choose day part is something im planning on adding later, where I'd want to get only specific data from the collection (exercises that were created only for a certain date).

How to use the information stored in mutableStateOf in Jetpack Compose

I have information in json and I retrieve it using retrofit2, everything works fine, I get the data in a List.
I need this information to fill elements in Jetpack Compose for which I use mutableStateOf to save the states.
My function that I use is the following:
fun jsonParsing(
dataRecox: MutableState<List<Event>>
) {
val TAG_LOGS = "Mariox"
val retrofit = Retrofit.Builder()
.baseUrl("http://myserversample.com/pGet/track/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val retrofitAPI = retrofit.create(APIService1::class.java)
retrofitAPI.getRecolector().enqueue(object : Callback<List<Event>> {
override fun onResponse(
call: Call<List<Event>>,
response: Response<List<Event>>
) {
val data = response.body()
val mydata = data!!
dataRecox.value = mydata
Log.i(TAG_LOGS, Gson().toJson(data))
}
override fun onFailure(call: Call<List<Event>>, t: Throwable) {
t.printStackTrace()
}
})
}
Mymodel:
data class Event (
val deviceID : Int,
val statusCode : Int,
val accountID : String,
val speedKPH : Int,
.
.
.
}
My composable:
#Composable
fun Greeting(name: String) {
val dataRecox = remember {
mutableStateOf(emptyList<Event>())
}
jsonParsing(dataRecox)
println("======")
println(dataRecox) // ok data
println(dataRecox.value). // ok data
//Uncommenting println(dataRecox.value[0]) I get empty.
//println(dataRecox.value[0])
//Text(text = dataRecox.value[0].uniqueID)
}
When I do not use the information in the console, by calling Greeting("Android") all the data is printed correctly:
The problem comes when I want to use that information:
For example, if I want to print in console println(dataRecox.value[0]) here it returns empty. If I want to use it with a composable Text: Text(text = dataRecox.value[0].uniqueID) it also gives me empty.
Can someone explain to me why this happens, because when I start using the information the data becomes empty.
The way you're doing is totally different of the recommended way... here's my suggestion.
Define a class to represent the screen's state.
data class ScreenState(
val events: List<Event> = emptyList(),
val error: Throwable? = null
)
Use a ViewModel to perform the API request and keep the screen state.
class EventsViewModel : ViewModel()
private val _screenState = MutableStateFlow<ScreenState>(ScreenState())
val screenState = _screenState.asStateFlow()
init {
jsonParsing()
}
fun jsonParsing() {
val TAG_LOGS = "Mariox"
val retrofit = Retrofit.Builder()
.baseUrl("http://myserversample.com/pGet/track/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val retrofitAPI = retrofit.create(APIService1::class.java)
retrofitAPI.getRecolector().enqueue(object : Callback<List<Event>> {
override fun onResponse(
call: Call<List<Event>>,
response: Response<List<Event>>
) {
val data = response.body()
Log.i(TAG_LOGS, Gson().toJson(data))
_screenState.update {
ScreenState(it.events)
}
}
override fun onFailure(call: Call<List<Event>>, t: Throwable) {
t.printStackTrace()
_screenState.update {
ScreenState(error = t)
}
}
})
}
}
Instantiate the ViewModel and use it in your screen...
#Composable
fun Greeting(name: String) {
val vm = viewModel<EventsViewModel>()
val screenState by vm.screenState.observeAsState()
LazyColumn(Modifier.fillMaxSize()) {
items(screenState.items) {
Text(it. accountID)
}
}
}

How to pass intent with Adapter in Kotlin

I would like to pass intent to another activity class with Adapter via OnClick function in Kotlin. However, when I am using the debug function, I noticed that the intent has not passed successfully. May I know how can I solve this? From various sources online, I realized that I may be required to called the gList inside the "OnClick" function, but I cant seem to work it out.
class GoalAdapter(
private var gList: ArrayList<GoalList>
) : RecyclerView.Adapter<GoalAdapter.MyViewHolder>(), View.OnClickListener{
private var connection : Connection? = null
private var statement : Statement? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val v: View = LayoutInflater.from(parent.context).inflate(R.layout.activity_goal_list, parent, false)
return MyViewHolder(v)
}
override fun getItemCount(): Int {
return gList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val list = gList[position]
holder.goal.text = list.gName
holder.tAmount.text = list.tAmount.toString()
holder.sAmount.text = list.sAmount.toString()
holder.gnote.text = list.Note
holder.gdate.text = list.dDate
val sqlCon = SQLCon()
connection = sqlCon.connectionClass()!!
holder.delete.setOnClickListener {
try
{
val sql : String= "DELETE FROM Goals where gName = '${list.gName}' "
statement = connection!!.createStatement()
statement!!.executeQuery(sql)
}
catch (e : Exception)
{ }
}
holder.update.setOnClickListener(this)
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var goal: TextView = itemView.findViewById(R.id.txtGoal)
var tAmount : TextView = itemView.findViewById(R.id.txtTargetAmount)
var sAmount : TextView = itemView.findViewById(R.id.txtSavedAmount)
var gnote : TextView = itemView.findViewById(R.id.txtNote)
var gdate : TextView = itemView.findViewById(R.id.txtDate)
var delete : Button = itemView.findViewById(R.id.btnDeleteGoal)
var update : Button = itemView.findViewById(R.id.btnUpdateGoal)
}
override fun onClick(view: View?) {
when(view?.id)
{
R.id.btnUpdateGoal ->
{
val intent = Intent(view.context, EditGoalActivity::class.java)
intent.putExtra("gName", R.id.txtGoal)
intent.putExtra("tAmount", R.id.txtTargetAmount )
intent.putExtra("sAmount", R.id.txtSavedAmount )
intent.putExtra("Note", R.id.txtNote )
intent.putExtra("dDate", R.id.txtDate )
view.context.startActivity(intent)
}
}
}
}

Struggling to access Spinner outside of my recycler view

I have tried two different ways to access my spinner. Without success thus far.
I want to load the data for each driver as chosen.
To give an idea of my app.
Code for adapter:
class TableViewAdapter(var tripsheetlist: Tripsheetlist) : RecyclerView.Adapter<TableViewAdapter.RowViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.table_list_item, parent, false)
return RowViewHolder(itemView) }
override fun getItemCount(): Int { return tripsheetlist.videos.size + 1 // one more to add header row
}
override fun onBindViewHolder(holder: RowViewHolder, position: Int) {
val rowPos = holder.adapterPosition
if (rowPos == 0) {
// Header Cells. Main Headings appear here
holder.itemView.apply {
setHeaderBg(txtWOrder)
setHeaderBg(txtDElNote)
setHeaderBg(txtCompany)
// setHeaderBg(txtAddress)
setHeaderBg(txtWeight)
setHeaderBg(txtbutton1)
setHeaderBg(txtbutton2)
setHeaderBg(txttvdone)
txtWOrder.text = "WOrder"
txtDElNote.text = "DElNote"
txtCompany.text = "Company"
// txtAddress.text = "Address"
txtWeight.text = "Weight"
txtbutton1.text = "Delivered"
txtbutton2.text = "Exception"
txttvdone.text = ""
}
} else {
val modal = tripsheetlist.videos[rowPos -1]
holder.itemView.apply {
setContentBg(txtWOrder)
setContentBg(txtDElNote)
setContentBg(txtCompany)
setContentBg(txtWeight)
setContentBg(txtbutton1)
setContentBg(txtbutton2)
setContentBg(txttvdone)
val list : MutableList<String> = ArrayList()
list.add("Deon")
list.add("Leon")
list.add("David")
list.add("Dick")
println(list)
val spinner : Spinner = findViewById(R.id.spnDriver)
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
val item :String = list[p2]
if (item == "David")
{
txtWOrder.text = modal.WOrder.toString()
txtDElNote.text = modal.DElNote.toString()
txtCompany.text = modal.name.toString()
txtWeight.text = modal.id.toString()
}
}
override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
I did it like this as a test for now. As I will get the drivers from my JSON. I don't have access to it yet so that is why the static values.
The problem I am getting now is: findViewById(R.id.spnDriver) must not be null
I first had my spinner class in my main activity and passed it over like this:
val list : MutableList<String> = ArrayList()
list.add("Deon")
list.add("Leon")
list.add("David")
list.add("Dick")
list.add("Jim")
list.add("Harry")
val adapter = ArrayAdapter( this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, list)
val spinner: Spinner = findViewById(R.id.spnDriver)
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
val item :String = list[p2]
Toast.makeText(this#MainActivity, "Driver $item selected", Toast.LENGTH_SHORT).show()
}
override fun onNothingSelected(p0: AdapterView<*>?) {
//empty
}
// insert code that activates data pull of tripsheet for driver= actifavte by method the class/object that activates the data pull. so datapuul(Driver)
}
limitDropDownHeight(spinner)
//drivers end
val btnLoadData: Button = findViewById(R.id.btnLoadData)
// weightsum(tvTotalweight, Tripsheetlist)
// totaldelNotes(tvTotaldelv,Tripsheetlist)
// setData(btnLoadData, Tripsheetlist )
fetchJson(spinner)
}
private fun fetchJson(spinner: Spinner) {
println("Attempting to Fetch JSON")
val url = "https://api.letsbuildthatapp.com/youtube/home_feed"
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
println("Failed to execute request") }
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
println(body)
val gson = GsonBuilder().create()
val tripsheetlist = gson.fromJson(body, Tripsheetlist::class.java)
runOnUiThread {
recyclerViewTripsheetlist.adapter = TableViewAdapter(tripsheetlist, spinner)
}
}
})
}
In my Adapter class I then called it with : val spinner = spnDriver
This led to a different error: AppCompatSpinner.setOnItemSelectedListener(android.widget.AdapterView$OnItemSelectedListener)' on a null object reference
But seems like it passed the val spinner =spnDriver without a problem.
Thank you for all input and help.
I found a solution. What I did was to keep the spinner inside my MainActivity and then just pass the result of the spinner to the adapter - where I wanted to use it.

hide Alert Dialog in kotlin

My current project downloading data from a server time I want to display a progress bar so the user knows what is going on. I have a simple alert dialog , l am try to add alert dialog when data json loading for user . when l launching app the alert dialog stay stick on screen even if the data loaded already and doesn't hide .
AsyncTask code :
inner class Arr : AsyncTask<String, String, String>(){
val progressDialog = AlertDialog.Builder(this#MainActivity)
val dialogView = layoutInflater.inflate(R.layout.progress_dialog,null)
val message = dialogView.findViewById<TextView>(R.id.message_id)
val dialog = progressDialog.create()
override fun onPreExecute() {
super.onPreExecute()
progressDialog.setMessage("loading")
progressDialog.setCancelable(false)
progressDialog.show()
}
// for build connection
override fun doInBackground(vararg url: String?): String{
var text : String
val connection = URL(url[0]).openConnection() as HttpURLConnection
try {
connection.connect()
text = connection.inputStream.use { it.reader().use{reader -> reader.readText()} }
} finally{
connection.disconnect()
}
return text
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
handleJson(result)
dialog.dismiss()
}
override fun onProgressUpdate(vararg text: String?) {
dialog.dismiss()
}
private fun handleJson (jsonString: String?){
dialog.dismiss()
val jsonObj = JSONObject(jsonString)
val result = jsonObj.getJSONObject("result")
val response = result.getJSONObject("response")
val airport = response.getJSONObject("airport")
val pluginData = airport.getJSONObject("pluginData")
val schedule = pluginData.getJSONObject("schedule")
val arrivals = schedule.getJSONObject("arrivals")
// val data = arrivals.getJSONObject("data")
val jsonArray = JSONArray(arrivals.get("data").toString())
val list = ArrayList<FlightShdu>()
var x = 0
while (x < jsonArray.length()){
val jsonObject = jsonArray.getJSONObject(x)
list.add(FlightShdu(
jsonObject.getJSONObject("flight").getJSONObject("identification").getJSONObject("number").getString("default"),
jsonObject.getJSONObject("flight").getJSONObject("airline").getString("name"),
jsonObject.getJSONObject("flight").getJSONObject("status").getString("text"),
jsonObject.getJSONObject("flight").getJSONObject("airline").getJSONObject("code").getString("icao"),
jsonObject.getJSONObject("flight").getJSONObject("time").getJSONObject("scheduled").getString("arrival")
))
x++
}
list.forEach(::println)
val adapter = ListAdapte(this#MainActivity,list)
flight_arrivel_list.adapter = adapter
}
} //
any solution please ?
Change to this:
override fun onPreExecute() {
super.onPreExecute()
dialog.setMessage("loading")
dialog.setCancelable(false)
dialog.show()
}
and hide it with:
dialog.dismiss();
you must refer to the AlertDialog object and not the AlertDialog.Builder.
In your onPreExecute()
override fun onPreExecute() {
...
progressDialog.show()
}
But in onPostExecute() you call different dialog to dismiss
override fun onPostExecute(result: String?) {
...
dialog.dismiss()
}
So you need to call progressDialog.dismiss() in onPostExecute().
progressDialog.dismiss() instead of dialog.dismiss()