I am trying to pass the data from NgoSignup1Fragment to NgoSignup2Fragment but i am getting null in NgoSignup2Fragment as you can see Debug Image, I didn't know what's the issue if anyone would help it will helpful for me.
class NgoSignup1Fragment : Fragment() {
private lateinit var communicator: Communicator
private lateinit var nextBtn: Button
private var name : TextInputEditText ?=null
private var mail : TextInputEditText ?=null
private var phone : TextInputEditText ?=null
private var add :TextInputEditText ?=null
private var pinCode :TextInputEditText ?=null
private var password :TextInputEditText ?=null
private var confirmPassword :TextInputEditText ?=null
private val emailPattern = "[a-zA-Z0-9._-]+#[a-z]+\\.+[a-z]+"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
val v = layoutInflater.inflate(R.layout.ngo_signup1_fragment, container, false)
communicator = activity as Communicator
nextBtn = v.findViewById(R.id.btn_ngosignup1_next)
name = v?.findViewById(R.id.et_ngosignup_name)
mail = v?.findViewById(R.id.et_ngosignup_mail)
phone = v?.findViewById(R.id.et_ngosignup_phone)
add = v?.findViewById(R.id.et_ngosignup_address)
pinCode = v?.findViewById(R.id.et_ngosignup_pincode)
password =v?.findViewById(R.id.et_ngosignup_password)
confirmPassword =v?.findViewById(R.id.et_ngosignup_confirmpassword)
nextBtn.setOnClickListener {
val orgName = name?.text.toString().trim()
val orgMail = mail?.text.toString().trim()
val orgPhone = phone?.text.toString().trim()
val officeAdd = add?.text.toString().trim()
val orgPinCode = pinCode?.text.toString().trim()
val orgPass = password?.text.toString().trim()
val confirmPass=confirmPassword?.text.toString().trim()
if (orgName.isEmpty()) {
name?.error = "Please provide organisation's name"
markButtonDisable(nextBtn)
}
if (orgMail.isEmpty()) {
mail?.error = "Mail cannot be empty"
markButtonDisable(nextBtn)
}
if (orgPhone.isEmpty()) {
phone?.error = "Enter your phone number"
markButtonDisable(nextBtn)
}
if (officeAdd.isEmpty()) {
add?.error = "Address cannot be empty"
markButtonDisable(nextBtn)
}
if (orgPinCode.isEmpty()) {
name?.error = "Name cannot be empty"
markButtonDisable(nextBtn)
}
if (orgPass.isEmpty()){
password?.error = "Password cannot be empty"
markButtonDisable(nextBtn)
}
if (!(orgMail.matches(emailPattern.toRegex()))) {
mail?.error = "Invalid email"
markButtonDisable(nextBtn)
}
if (!(isValidPassword(orgPass))) {
password?.error = "Password format is invalid"
markButtonDisable(nextBtn)
}
if(orgPass != confirmPass){
confirmPassword?.error = "Passwords doesn't match"
markButtonDisable(nextBtn)
}else{
communicator.passDataCom(orgName,orgMail,orgPhone,officeAdd,orgPinCode,orgPass)
activity?.supportFragmentManager?.beginTransaction()
?.replace(
R.id.fragment_container1,
NgoSignup2Fragment()
)?.addToBackStack(null)?.commit()
}
//this opens up the sign up 2 page
//Put the value
//Put the value
}
return v
}
private fun isValidPassword(password: String): Boolean {
val passwordREGEX = Pattern.compile(
"^" +
"(?=.*[0-9])" + //at least 1 digit
"(?=.*[a-z])" + //at least 1 lower case letter
"(?=.*[A-Z])" + //at least 1 upper case letter
"(?=.*[a-zA-Z])" + //any letter
"(?=.*[##$%^&+=])" + //at least 1 special character
"(?=\\S+$)" + //no white spaces
".{8,}" + //at least 8 characters
"$"
)
return passwordREGEX.matcher(password).matches()
}
private fun markButtonDisable(b:Button){
b.isEnabled =false
b.setBackgroundColor(resources.getColor(R.color.theme_button_disabled))
}}
my interface which i am using to pass data :
interface Communicator {
fun passDataCom(
orgName: String,
orgMail: String,
orgPhone: String,
officeAdd: String,
orgPin: String,
orgPass: String
)}
This is MainActivity where the string values are passed Till here all the variables values are correct
class MainActivity : AppCompatActivity(),Communicator {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/*This part of the code is used to set the default theme as the theme was set to the splash screen before setting the main activity layout
remove the comment tag for adding the logic*/
setTheme(R.style.Theme_Samarpan)
setContentView(R.layout.activity_main)
addFragment()
}
private fun addFragment() {
val userSignInLayout= LoginFragment()
supportFragmentManager.beginTransaction().add(R.id.fragment_container1,userSignInLayout).commit()
}
override fun passDataCom(
orgName: String,
orgMail: String,
orgPhone: String,
officeAdd: String,
orgPin: String,
orgPass: String
) {
val bundle=Bundle()
bundle.putString("Name",orgName)
bundle.putString("Mail",orgMail)
bundle.putString("Phone",orgPhone)
bundle.putString("Address",officeAdd)
bundle.putString("PinCode",orgPin)
bundle.putString("Password",orgPass)
val transaction=this.supportFragmentManager.beginTransaction()
val ngoSignUp2 = NgoSignup2Fragment()
ngoSignUp2.arguments = bundle
transaction. Commit()
}}
This is the fragment where i want to send the values but i m getting null values to all the variables .
class NgoSignup2Fragment : Fragment(){
private var v : View?=null
private var btnNgoRegister: Button?=null
private var tilCategoryOthers:TextInputLayout?=null
private var etCategoryOthers:TextInputEditText?=null
private var orgName:String =""
private var orgMail:String =""
private var orgPhone:String =""
private var officeAdd:String =""
private var orgPin:String =""
private var orgPass:String =""
private var category:String=""
private lateinit var registerAuth: FirebaseAuth
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
v = layoutInflater.inflate(R.layout.ngo_signup2_fragment,container,false)
btnNgoRegister=v?.findViewById(R.id.btnNgoRegister)
tilCategoryOthers=v?.findViewById(R.id.til_category_others)
etCategoryOthers=v?.findViewById(R.id.et_category_others)
val organisationTypes = resources.getStringArray(R.array.organisation_type)
val arrayAdapter = ArrayAdapter(requireContext(),R.layout.dropdown_item,organisationTypes)
val autoCompleteTV= v?.findViewById<AutoCompleteTextView>(R.id.ngosignup_select_orgtype_items)
autoCompleteTV?.setAdapter(arrayAdapter)
category=autoCompleteTV?.text.toString().trim()
registerAuth= Firebase.auth
orgName= arguments?.getString("Name").toString().trim()
orgMail= arguments?.getString("Mail").toString().trim()
orgPhone=arguments?.getString("Phone").toString().trim()
officeAdd=arguments?.getString("Address").toString().trim()
orgPin=arguments?.getString("PinCode").toString().trim()
orgPass=arguments?.getString("Password").toString().trim()
btnNgoRegister?.setOnClickListener {
Toast.makeText(activity, orgName, Toast.LENGTH_SHORT).show()
if(category == "Others"){
//get the category from the user of the type he is from other than the list
btnNgoRegister?.isEnabled=false
tilCategoryOthers?.visibility=View.VISIBLE
category=etCategoryOthers?.text.toString()
btnNgoRegister?.isEnabled=true
}
val db = FirebaseFirestore.getInstance()
try{
registerAuth.createUserWithEmailAndPassword(orgMail,orgPass)
.addOnCompleteListener{ task->
if(task.isSuccessful){
val ngo: FirebaseUser? =registerAuth.currentUser
Toast.makeText(
activity,
"Thank You! for choosing us",
Toast.LENGTH_SHORT
).show()
val documentReference : DocumentReference =db.collection("users").document(
ngo?.uid ?: ""
)
val ngoInfo :MutableMap<String,Any> = HashMap()
ngoInfo["Full Name"]= orgName
ngoInfo["Email"]= orgMail
ngoInfo["PhoneNumber"]=orgPhone
ngoInfo["Address"]=officeAdd
ngoInfo["Pin Code"]=orgPin
ngoInfo["isDonor"]="0"
// add the value of the org type from the dropdown and upload document work
documentReference.set(ngoInfo).addOnSuccessListener {
Log.d(ContentValues.TAG, "User data for $orgName was collected successfully ")
}.addOnFailureListener{ e ->
Log.w(ContentValues.TAG, "Error adding data", e)
}
}else{
Toast.makeText(
activity,
task.exception!!.message.toString(),
Toast.LENGTH_SHORT
).show()
}
}
}
catch(e :Exception){
Toast.makeText(context, "Fields cannot be empty $e", Toast.LENGTH_SHORT).show()
}
}
return v
}}
Related
I've been struggling with the problem for a long time and I can't solve it.I'm in EditActivity trying to add a key to the data from the firebase that I get from it with the help of Ad and process it using the AdsManager.
The key should not be equal to zero. In this line I check if the key is zero, then the Firebase writes data to empty.db.child (ad.key?: "Empty"). SetValue (ad). When I load the data to the Firebase, it shows them empty. Without displaying the key. You know what the problem is?
Ad
data class Ad(
var user_id : String? = null ,
var name : String? = null ,
var button1 : String? = null ,
val textTex : String? = null ,
val textk : String? = null ,
val description : String? = null,
val name_ads: String?=null,
val key :String? =null
)
AdsManager
class AdsManager(val readDataColbak : ReadDataColbak?) {
private lateinit var auth: FirebaseAuth
val db =Firebase.database.getReference("main")
fun pubilshAd(ad :Ad) {
db.child(ad.key?: "empty").setValue(ad)
}
fun ReadDataDb() {
db.addListenerForSingleValueEvent(object :ValueEventListener{
override fun onDataChange(snapshot : DataSnapshot) {
val adArray =ArrayList<Ad>()
for (item in snapshot.children){
val ad =item.children.iterator().next().child("ad").getValue(Ad::class.java)
adArray.add(ad !!)
}
readDataColbak?.readData(adArray)
}
override fun onCancelled(error : DatabaseError) {
}
})
}
}
EditActivity1
class EditActivity1: AppCompatActivity(), FfragmentInterfes{
lateinit var mBinder : ActivityEdit1Binding
private var dialog=D()
private var chooseImageFrog:FragmentList? =null
val adsManager = AdsManager(null)
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
imageAdapter = ImageAdapter()
mBinder=ActivityEdit1Binding.inflate(layoutInflater)
setContentView(mBinder.root)
init()
}
fun onClickPublish(view : View) {
adsManager.pubilshAd(fillAd())
}
private fun fillAd() : Ad {
var ad : Ad
mBinder.apply {
ad= Ad(
name_ads.text.toString(),
user_id.text.toString(),
name.text.toString(),
button1.text.toString(),
description.text.toString(),
textk.text.toString(),
adsManager.db.push().key
)
}
return ad
}
I'm trying to build a simple app where the user enters his email address to sign up over Firebase with MVVM (Model View ViewModel).
when i try to observe the data in the view inside a fragment from the ViewModel the whole app crashes.
The error message says: Error inflating class androidx.fragment.app.FragmentContainerView
But when i remove the observing part from the View(The Login fragment the app runs correctlly)
Can someone help me to fix that problem?
the App Repository
class AppRepo {
private var application: Application? = null
val userMutableLiveData: MutableLiveData<FirebaseUser>? = null
val loggedOutMutableLiveData: MutableLiveData<Boolean>? = null
val usernameMutableLiveData: MutableLiveData<String>? = null
val uriProfilePicMutableLiveData: MutableLiveData<Uri>? = null
private var firebaseAuth: FirebaseAuth? = null
constructor(application: Application?) {
this.application = application
firebaseAuth = FirebaseAuth.getInstance()
if (firebaseAuth!!.currentUser != null) {
val userID = Objects.requireNonNull(FirebaseAuth.getInstance().currentUser)!!
.uid
userMutableLiveData!!.postValue(firebaseAuth!!.currentUser)
}
}
#RequiresApi(api = Build.VERSION_CODES.P)
fun loginUsers(email: String?, password: String?) {
firebaseAuth!!.signInWithEmailAndPassword(email!!, password!!).addOnCompleteListener(
application!!.mainExecutor,
{ task ->
if (task.isSuccessful) {
userMutableLiveData!!.postValue(firebaseAuth!!.currentUser)
} else {
Toast.makeText(
application,
"Logging in failed: " + task.exception,
Toast.LENGTH_LONG
).show()
}
})
}
#JvmName("getUserMutableLiveData1")
fun getUserMutableLiveData(): MutableLiveData<FirebaseUser>? {
return userMutableLiveData
}
}
the ViewModel
open class ViewModel(application: Application) : AndroidViewModel(application) {
private var appRepo: AppRepo? = null
private var userMutableLiveData: MutableLiveData<FirebaseUser>? = null
private var loggedOutMutableLiveData: MutableLiveData<Boolean>? = null
private var documentSnapshotMutableLiveData: MutableLiveData<String>? = null
private var uriProfilePocMutableLiveData: MutableLiveData<Uri>? = null
open fun ViewModel(application: Application) {
appRepo = AppRepo(application)
userMutableLiveData = appRepo!!.getUserMutableLiveData()
loggedOutMutableLiveData = appRepo!!.getLoggedOutMutableLiveData()
documentSnapshotMutableLiveData = appRepo!!.getUsernameMutableLiveData()
uriProfilePocMutableLiveData = appRepo!!.getUriProfilePicMutableLiveData()
}
#RequiresApi(Build.VERSION_CODES.P)
open fun login(email: String?, password: String?) {
appRepo!!.loginUsers(email, password)
}
open fun getUserMutableLiveData(): MutableLiveData<FirebaseUser>? {
return userMutableLiveData
}
open fun getUsernameMutableLiveData(): MutableLiveData<String>? {
return documentSnapshotMutableLiveData
}
open fun getUriProfilePocMutableLiveData(): MutableLiveData<Uri>? {
return uriProfilePocMutableLiveData
}
}
the LoginFragment
abstract class LoginFragment : Fragment() {
private var emailEditText: EditText? = null
private var passwordEditText:EditText? = null
private var loginButton: Button? = null
private var signupButton: Button? = null
private var resetPasswordButton:Button? = null
private var viewModel: ViewModel? = null
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_login, container, false)
emailEditText = view.findViewById(R.id.username)
passwordEditText = view.findViewById(R.id.password)
loginButton = view.findViewById(R.id.login)
loginButton!!.setOnClickListener(View.OnClickListener {
val email = emailEditText!!.getText().toString().trim { it <= ' ' }
val password = passwordEditText!!.getText().toString().trim { it <= ' ' }
if (email.isNotEmpty() && password.isNotEmpty()) {
viewModel!!.login(email, password)
}
})
return view
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
activity?.let {
viewModel!!.getUserMutableLiveData()!!.observe(
it,
{ firebaseUser ->
if (firebaseUser != null) {
Navigation.findNavController(requireView())
.navigate(R.id.action_loginFragment3_to_mainUIFragment)
}
})
}
}
}
XML File MainActivity
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
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"
tools:context=".ui.MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="false"
app:navGraph="#navigation/nav_graph"
tools:layout_editor_absoluteX="17dp"
tools:layout_editor_absoluteY="221dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
I am using a recycleview to display latest inputs from the user. When I click edit text, the old inputs move up and the keyboard shows in the app. But when I enter the next entry, I have to minimize the keyboard to be able to see the new entry. It doesnt move up - this was expected behaviour as the recycleview is updated.
Stage 1)
Old Entry
Old Entry
Stage 2) Click edit text to make new entry
Old Entry
Old Entry
Keyboard
Stage 3) New text is entered
Old Entry
Old Entry
Keyboard
Stage 4) Keyboard is hidden,/minimized
Old Entry
Old Entry
New Entry
The layout is stacked from the end... what can I change to make this work?
AndroidManifest setting
<activity
android:name=".Contacts.ui.ContactDetailsHome"
android:configChanges="orientation"
android:parentActivityName=".MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
fragment code
class ContactRelationship : Fragment() {
companion object {
#JvmStatic
fun start(context: Context, contact: Contact?, isEdit: Boolean) {
val starter = Intent(context, ContactRelationship::class.java)
.putExtra("contact", contact as Serializable)
.putExtra("Edit", isEdit)
context.startActivity(starter)
}
}
private val _updatesLiveData = MutableLiveData<ArrayList<ContUPDt>>()
private val updatesLiveData: LiveData<ArrayList<ContUPDt>> = _updatesLiveData
var firebaseUser: FirebaseUser? = null //the used id of the user using the app
var userLookupKey: String = ""
private lateinit var contact: Contact
var mupdateList: List<ContUPDt>? = null
var contUpdateAdapter: ContUpdateAdapter? = null
var reference: DatabaseReference? = null
lateinit var rvContRelUpdate: RecyclerView
private lateinit var progressBar: ProgressDialog
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
val view: View =
inflater.inflate(R.layout.fragment_view_contact_relationship, container, false)
progressBar = ProgressDialog(activity)
progressBar.setCancelable(false)
firebaseUser = FirebaseAuth.getInstance().currentUser
rvContRelUpdate = view.findViewById(R.id.rvContRelUpdate)
rvContRelUpdate.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(activity)
linearLayoutManager.stackFromEnd = true
rvContRelUpdate.layoutManager = linearLayoutManager
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
contact = (activity?.intent?.getSerializableExtra("contact") as Contact)
//assigning it to fields to be displayed
userLookupKey = contact.lookupKey
val contId = contact.id
//get updates
retrieveUpdates(userLookupKey)
//Implementing Send Update
send_update_btn.setOnClickListener {
val updateTxt = text_messageact.text.toString()
if (updateTxt == "") {
Toast.makeText(activity, "The update is empty.", Toast.LENGTH_LONG)
.show()
} else {
sendMessageToUser(userLookupKey, contId, updateTxt)
}
text_messageact.setText("")
}
private fun sendMessageToUser(userLookupKey: String, contId: String, updateMsg: String) {
val currentCalendar = Calendar.getInstance()
//creating object in DB
val db = activity?.let { AppDatabase.getDatabase(it) }
val ev = ContUPDt(
0,
userLookupKey,
contId,
currentCalendar.timeInMillis,
updateMsg,
null,
"Update"
)
db!!.ContUpdateDao().addcontUpdate(ev)
}
private fun retrieveUpdates(userLookupKey: String) {
val mupdateList = ArrayList<ContUPDt>()
val db = AppDatabase.getDatabase(requireActivity())
db.ContUpdateDao().getcontUpdate(userLookupKey).observe(viewLifecycleOwner, Observer {
val contUpdt = it
mupdateList.clear()
for (i in contUpdt) {
mupdateList.add(i)
}
})
contUpdateAdapter = ContUpdateAdapter(requireActivity(), mupdateList)
rvContRelUpdate.adapter = contUpdateAdapter
}
}
Adapter code
class ContUpdateAdapter(
mContext: Context,
mupdateList: List<ContUPDt>
) : RecyclerView.Adapter<ContUpdateAdapter.ViewHolder?>() {
private val mContext: Context
private val mupdateList: List<ContUPDt>
init {
this.mContext = mContext
this.mupdateList = mupdateList
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var updateDTTime: TextView? = null
var updateMessage: TextView? = null
var updateType: TextView? = null
init {
updateDTTime = itemView.findViewById(R.id.updateDTTime)
updateMessage = itemView.findViewById(R.id.updateMessage)
updateType = itemView.findViewById(R.id.updateType)
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
position: Int
): ViewHolder {
return ViewHolder (
LayoutInflater.from(parent.context)
.inflate(R.layout.contactupdate, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contUpdte: ContUPDt = mupdateList[position]
val formatter = SimpleDateFormat(" E, HH:MM a, dd MMM yyyy", Locale.getDefault())
val updatetime = formatter.format(contUpdte.timestamp)
holder.updateDTTime!!.text = updatetime
holder.updateMessage!!.text = contUpdte.update
holder.updateType!!.text = contUpdte.actType
}
override fun getItemCount(): Int {
return mupdateList.size
}
}
Just scroll RecyclerView to last position after adding new item:
rvContRelUpdate.scrollToPosition(contUpdateAdapter.itemCount - 1)
First I have declared the variables in the layout file
<data>
<variable
name="signUpViewModel"
type="ac.connect.ui.signup.SignUpViewModel" />
</data>
Now I'm trying to use a function of StringExtension class which takes string value as parameter and to set the result to textView
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:textStyle="bold"
android:background="#C1BDBD"
android:textColor="#3D3C3C"
app:capitalizeFirstLetter="#{signUpViewModel.name}" />
capitalize First Letter function
fun capitalizeFirstLetter(value: String): String {
var ans = ""
val words = value.split(" ")
words.forEach {
ans += it.capitalize() + " "
}
return ans
}
ViewModel
class SignUpViewModel(private val setProfileUseCase: SetProfileUseCase) :
ViewModel() {
private val _profile = MutableLiveData<ProfileModel>()
val profile: LiveData<ProfileModel>
get() = _profile
private val _name = MutableLiveData<String>()
val name: LiveData<String>
get() = _name
fun setName(name: Editable) {
_name.value = name.toString()
}
fun setProfileData() {
viewModelScope.launch {
val profile = ProfileModel(
name = "kamal nayan",
branch = "CSE",
gender = "Male",
mobileNumber = "+91-73555555517",
rollNo = "GCS/345353",
uid = "ghafagaraggGGG"
)
val response = setProfileUseCase.invoke(profile)
_profile.value = profile
response.successOrError(::handleProductDetailsSuccess, ::handleSignUpFailure)
}
}
private fun handleProductDetailsSuccess(response: Boolean) {
_name.value = "User Data Uploaded Successfully"
}
private fun handleSignUpFailure(failure: Failure, error: ErrorResponse?) {
Timber.log(Log.ERROR, error?.message)
}
}
Fragment Code:
class SignUpFragment : Fragment(R.layout.fragment_sign_up) {
private val viewModel: SignUpViewModel by viewModel()
private var binding by autoCleared<FragmentSignUpBinding>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentSignUpBinding.bind(view)
binding.signUpViewModel = viewModel
binding.lifecycleOwner = this
binding.signUp.setOnClickListener {
viewModel.setProfileData()
}
}
companion object {
fun newInstance(): SignUpFragment {
return SignUpFragment()
}
}
}
The output is blank , like no text in the textView
Kindly help me with this, Thanks in advance.
I think the problem is you are not setting the value of the variable stringExtensions when setting up your DataBinding
import ac.connect.utils.StringExtensions
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentSignUpBinding.bind(view)
binding.signUpViewModel = viewModel
// binding.stringExtensions = StringExtensions() // If it is a class
// binding.stringExtensions = StringExtensions // If it is an object
binding.lifecycleOwner = this
binding.signUp.setOnClickListener {
viewModel.setProfileData()
}
}
If I understand right you need make BindingAdapter. So you need rewrite your 'capitalizeFirstLetter' function as below.
#BindingAdapter("app:capitalizeFirstLetter")
#JvmStatic fun capitalizeFirstLetter(textView: TextView, value: String){
var ans = ""
val words = value.split(" ")
words.forEach {
ans += it.capitalize() + " "
}
textView.setText(ans)
}
Also I didn't see where you call setName function. Are you sure that _name.value is not empty?
Here's the code where i am getting exception, tried various ways to implement context but nothing is working out.
class GrowthStoryFragment : Fragment() {
private val TAG = "GrowthStoryFragment"
companion object{
private var countryID = "1"
private var date = "MAT TY"
private var spec = "val"
private var businessUnitID = "2"
private var category = "Fresh Milk"
private var firstReportTypeId = "1" //fixed for growth story and share story
private var isGroup = "false" //fixed to false
}
private val backendApi = WinRetrofitHelper.winApiInstance()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_growth_story, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getSpinnerResponse(businessUnitID, isGroup,firstReportTypeId)
getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)
growth_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val item = parent?.getItemAtPosition(position) as RespTwo
category = item.nameValue
Log.e(TAG,"Category name is: " + category)
getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)
}
}
}
private fun getSpinnerResponse(businessUnitID: String, isGroup: String, firstReportTypeId: String){
val request = backendApi.getCategoryBusinessUnit(businessUnitID, isGroup, firstReportTypeId)
request.enqueue(object : Callback<List<RespTwo>> {
override fun onFailure(call: Call<List<RespTwo>>?, t: Throwable?) {
Log.e(TAG, "Failure Super Region Name: ")
}
override fun onResponse(call: Call<List<RespTwo>>?, response: Response<List<RespTwo>>?) {
val myresponse = response?.body()
if (response?.body() != null && !response?.body()!!.isEmpty()) {
growth_spinner.adapter = GrowthSpinnerAdapter(response?.body())
Log.e(TAG, "Super Region Name: " + myresponse?.get(0)?.nameValue)
} else {
Toast.makeText(context!!.applicationContext, "Data Not Available!", Toast.LENGTH_LONG).show()
}
}
})
}
private fun getSuperRegionName(countryID: String, date: String, spec: String, superMarket: String,businessUnitID: String, category: String, firstReportTypeId: String, isGroup: String) {
val request = backendApi.getSuperRegion(countryID)
request.enqueue(object : Callback<List<RespMy>> {
override fun onFailure(call: Call<List<RespMy>>?, t: Throwable?) {
Log.e(TAG, "Failure Super Region Name: ")
}
override fun onResponse(call: Call<List<RespMy>>?, response: Response<List<RespMy>>?) {
val myresponse = response?.body()
if (response?.body() != null && !response?.body()!!.isEmpty()) {
getDataFromApi(countryID, date, spec, myresponse?.get(0)!!.nameValue, businessUnitID, category, firstReportTypeId, isGroup)
Log.e(TAG, "Super Region Name: " +countryID+" "+ date+" "+ spec+" "+ myresponse?.get(0)?.nameValue+" "+businessUnitID+" "+ category+" "+ firstReportTypeId+" " + isGroup+" ")
} else {
Toast.makeText(myApplicationContext, "Data Not Available!", Toast.LENGTH_LONG).show()
}
}
})
}
}
Please suggest something and i have heard a viewModel conversion of the requests made directly from fragments can fix this out but i don't know how to do that. Please help in either way.
Update:
Don't want to use static context here
ViewModel and Repository pattern is way to go.
You are doing async network call on Main thread, very bad idea.
For learning purposes - here is how to get your code working:
replace:
myApplicationContext = context!!.applicationContext
with:
myApplicationContext = requireContext()
or better - get rid of this variable entirely and just use requireContext() instead.
Toasts are usually applied to the activity rather than an generic context, and demanding the context via context!! should be avoided; it is optional for a reason. I would try the following after defining #string/data_not_available and #string/super_region_name_template in the string resource xml:
val body = response?.body()
if (body?.isNotEmpty() == true) {
growth_spinner.adapter = GrowthSpinnerAdapter(body)
Log.e(TAG, getString(R.string.super_region_name_template, body.get(0).nameValue)) // if applicable, use .first() over .get(0)
} else {
activity?.run {
Toast.makeText(this, getString(R.string.data_not_available), Toast.LENGTH_LONG).show()
}
}
try to use this
myApplicationContext: Context = this.context ?: return
then
Toast.makeText(myApplicationContext, "Data Not Available!",Toast.LENGTH_LONG).show()
for more details, you can see this link