'these two lines of codes, crash my app, when I change app theme but I need them, what should I do? Android Studio
I tried different ways untill I figured out that the problem is with the bellow these textViews:
name.text = user.name+" "+user.lastName
phoneNumber.text = user.phoneNumber
I used them into a Datasnapshot to retrive {user name and last name and phone number} data on navigationdrawer header like bellow:
private fun getUserData() {
val scoresRef = Firebase.database.getReference("Users")
scoresRef.child(uid).addValueEventListener(object : ValueEventListener {
@SuppressLint("SetTextI18n")
override fun onDataChange(snapshot: DataSnapshot) {
user = snapshot.getValue(User::class.java)!!
val name = findViewById<TextView>(R.id.tvFirstNameAndLastName)
val phoneNumber = findViewById<TextView>(R.id.tvPhoneNumber)
name.text = user.name+" "+user.lastName
phoneNumber.text = user.phoneNumber
getUserProfile()
}
override fun onCancelled(error: DatabaseError) {
finish()
}
})
}
when I remove that two lines, everything works fine and no problem with theme and changing language, but by using them data fetching is OK and no problem too, I just want to change app theme or language but this error shows in logcat after app crashed :
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at af.azdreams.myconquer.DashboardActivity$getUserData$1.onDataChange(DashboardActivity.kt:293)
1- this is my activity_dashboard.xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DashboardActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/Orange"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageButton
android:id="@+id/btnSearchUsers"
android:layout_width="wrap_content"
android:background="#0000"
android:layout_height="wrap_content"
app:srcCompat="@drawable/icon_search"
android:contentDescription="@string/todo" />
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.tabs.TabLayout
app:tabTextAppearance="@style/MineCustomTabText"
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header"
app:itemTextAppearance="@style/menu"
app:menu="@menu/nav_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
2- this is the DashboardActivity.kt :
import af.azdreams.myconquer.databinding.ActivityDashboardBinding
import af.azdreams.myconquer.fragments.ExploreFragment
import af.azdreams.myconquer.fragments.FlightsFragment
import af.azdreams.myconquer.fragments.TravelFragment
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.res.Configuration
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.navigation.NavigationView
import com.google.android.material.tabs.TabLayout
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference
import java.io.File
import java.util.*
class DashboardActivity : AppCompatActivity() {
private lateinit var storageReference: StorageReference
private lateinit var databaseReference: DatabaseReference
private lateinit var user: User
private lateinit var uid: String
private var toolbar: Toolbar? = null
private var viewPager: ViewPager? = null
private var tabLayout: TabLayout? = null
private var exploreFragment: ExploreFragment? = null
private var flightsFragment: FlightsFragment? = null
private var travelFragment: TravelFragment? = null
private lateinit var auth: FirebaseAuth
private lateinit var binding: ActivityDashboardBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
auth = FirebaseAuth.getInstance()
uid = auth.currentUser?.uid.toString()
databaseReference = FirebaseDatabase.getInstance().getReference("Users")
if (uid.isNotEmpty()){
getUserData()
}
loadLocale()
binding = ActivityDashboardBinding.inflate(layoutInflater)
setContentView(binding.root)
onClickListenerSearchUser()
val scoresRef = Firebase.database.getReference("Users")
scoresRef.keepSynced(true)
initData()
checkTheme()
findViewById<Toolbar>(R.id.toolbar).also { toolbar = it }
setSupportActionBar(toolbar)
findViewById<ViewPager>(R.id.viewPager).also { viewPager = it }
findViewById<TabLayout>(R.id.tabLayout).also { tabLayout = it }
exploreFragment = ExploreFragment()
flightsFragment = FlightsFragment()
travelFragment = TravelFragment()
with(tabLayout) { this?.setupWithViewPager(viewPager) }
val viewPagerAdapter = ViewPagerAdapter(supportFragmentManager, 0)
viewPagerAdapter.addFragment(exploreFragment!!,resources.getString(R.string.home))
viewPagerAdapter.addFragment(flightsFragment!!, "Flights")
viewPagerAdapter.addFragment(travelFragment!!,resources.getString(R.string.dictionary))
with(viewPager) {
this!!.adapter = viewPagerAdapter
}
val tabLayout = tabLayout
tabLayout?.getTabAt(0)?.setIcon(R.drawable.icon_home)
tabLayout?.getTabAt(1)?.setIcon(R.drawable.icon_flights)
tabLayout?.getTabAt(2)?.setIcon(R.drawable.icon_dictionary)
val badgeDrawable: BadgeDrawable = tabLayout?.getTabAt(0)!!.orCreateBadge
badgeDrawable.isVisible = true
badgeDrawable.number = 12
val drawerLayout = findViewById<DrawerLayout>(af.azdreams.myconquer.R.id.drawerLayout)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val navView = findViewById<NavigationView>(R.id.navView)
val toggle = ActionBarDrawerToggle(this,drawerLayout,toolbar, R.string.open,
R.string.close)
toggle.isDrawerIndicatorEnabled = true
supportActionBar?.setDisplayShowTitleEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener {
when(it.itemId){
R.id.itmFetch ->startActivity(Intent(this,UserProfileActivity::class.java))
R.id.itmProfile ->startActivity(Intent(this,Profile::class.java))
R.id.itmLanguage ->showChangeLanguageDialog()
R.id.itmAppearance ->chooseThemeDialog()
R.id.itmSignOut ->basicAlert()
R.id.itmRateAndComments ->{
val url = "https://play.google.com/store/apps/details?id=org.telegram.plus"
if (url.startsWith("https://") || url.startsWith("http://")) {
val uri = Uri.parse(url)
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)
}
}
R.id.itmAbout ->startActivity(Intent(this,About::class.java))
}
true
}
}
private var backPressedTime:Long = 0
private lateinit var backToast: Toast
override fun onBackPressed() {
backToast = Toast.makeText(this,resources.getString(R.string.press_back_again_to_leave_the_app), Toast.LENGTH_SHORT)
if (backPressedTime + 2000 > System.currentTimeMillis()) {
backToast.cancel()
super.onBackPressed()
return
} else {
backToast.show()
}
backPressedTime = System.currentTimeMillis()
}
private fun showChangeLanguageDialog() {
val pref = getSharedPreferences("Settings", MODE_PRIVATE)
val mBuilder = AlertDialog.Builder(this)
val listItems = arrayOf("English", "فارسی دری", "پښتو")
var checkedItem = 0
when {
pref.getString("My_Lang", "en").equals("en") -> {
checkedItem = 0
}
pref.getString("My_Lang", "en").equals("fa") -> {
checkedItem = 1
}
pref.getString("My_Lang", "en").equals("ps") -> {
checkedItem = 2
}
}
mBuilder.setSingleChoiceItems(listItems, checkedItem) { dialogInterface: DialogInterface, i: Int ->
when (i) {
0 -> {
setLocale("en")
startActivity(Intent(this,SplashScreen::class.java))
}
1 -> {
setLocale("fa")
startActivity(Intent(this,SplashScreen::class.java))
}
2 -> {
setLocale("ps")
startActivity(Intent(this,SplashScreen::class.java))
}
}
dialogInterface.dismiss()
}
val mDialog = mBuilder.create()
mDialog.show()
}
private fun setLocale(lang: String?) {
val locale = Locale(lang)
Locale.setDefault(locale)
val config = Configuration()
config.locale = locale
baseContext.resources.updateConfiguration(config, baseContext.resources.displayMetrics)
val editor = getSharedPreferences("Settings", MODE_PRIVATE).edit()
editor.putString("My_Lang", lang)
editor.apply()
}
private fun loadLocale() {
val prefs = getSharedPreferences("Settings", MODE_PRIVATE)
val language = prefs.getString("My_Lang", "")
setLocale(language)
}
private fun basicAlert(){
val positiveButtonClick = { _: DialogInterface, _: Int -> }
val negativeButtonClick = { _: DialogInterface, _: Int -> }
val builder = AlertDialog.Builder(this)
with(builder) {
setMessage(R.string.do_you_want_to_sign_out_from_your_my_conquer_account)
setPositiveButton(R.string.yes, positiveButtonClick)
setPositiveButton(R.string.yes) { _: DialogInterface, _: Int ->
auth.signOut()
startActivity(Intent(this@DashboardActivity, SignInActivity::class.java))
finish()
}
setNegativeButton(R.string.no, negativeButtonClick)
show()
}
}
private fun initData(){
auth = FirebaseAuth.getInstance()
setUserEmail()
}
private fun setUserEmail(){
getCurrentUserEmail()
}
private fun getCurrentUserEmail():String? {
return auth.currentUser?.email
}
private fun chooseThemeDialog() {
val builder = AlertDialog.Builder(this)
val styles = arrayOf(resources.getString(R.string.light),resources.getString(R.string.dark),resources.getString(
R.string.system_default))
val checkedItem = MyPreferences(this).darkMode
builder.setSingleChoiceItems(styles, checkedItem) { dialog, which ->
when (which) {
0 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
MyPreferences(this).darkMode = 0
delegate.applyDayNight()
dialog.dismiss()
}
1 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
MyPreferences(this).darkMode = 1
delegate.applyDayNight()
dialog.dismiss()
}
2 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
MyPreferences(this).darkMode = 2
delegate.applyDayNight()
dialog.dismiss()
}
}
}
val dialog = builder.create()
dialog.show()
}
class MyPreferences(context: Context?) {
companion object {
private const val DARK_STATUS = ""
}
private val preferences = PreferenceManager.getDefaultSharedPreferences(context)
var darkMode = preferences.getInt(DARK_STATUS, 0)
set(value) = preferences.edit().putInt(DARK_STATUS, value).apply()
}
private fun checkTheme() {
when (MyPreferences(this).darkMode) {
0 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
delegate.applyDayNight()
}
1 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
delegate.applyDayNight()
}
2 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
delegate.applyDayNight()
}
}
}
private class ViewPagerAdapter(fm: FragmentManager, behavior: Int) :
FragmentPagerAdapter(fm, behavior) {
private val fragments: MutableList<Fragment> = ArrayList()
private val fragmentTitle: MutableList<String> = ArrayList()
fun addFragment(fragment: Fragment, title: String) {
fragments.add(fragment)
fragmentTitle.add(title)
}
override fun getItem(position: Int): Fragment {
return fragments[position]
}
override fun getCount(): Int {
return fragments.size
}
override fun getPageTitle(position: Int): CharSequence {
return fragmentTitle[position]
}
}
private fun getUserData() {
val scoresRef = Firebase.database.getReference("Users")
scoresRef.child(uid).addValueEventListener(object : ValueEventListener {
@SuppressLint("SetTextI18n")
override fun onDataChange(snapshot: DataSnapshot) {
user = snapshot.getValue(User::class.java)!!
val name = findViewById<TextView>(R.id.tvFirstNameAndLastName)
val phoneNumber = findViewById<TextView>(R.id.tvPhoneNumber)
name.text = user.name+" "+user.lastName
phoneNumber.text = user.phoneNumber
getUserProfile()
}
override fun onCancelled(error: DatabaseError) {
finish()
}
})
}
private fun getUserProfile() {
val navigationView = binding.navView
val header: View = navigationView.getHeaderView(0)
storageReference = FirebaseStorage.getInstance().reference.child("Users/$uid")
val localeFile = File.createTempFile("tempFile","")
storageReference.getFile(localeFile).addOnSuccessListener {
val bitmap = BitmapFactory.decodeFile(localeFile.absolutePath)
val picture = header.findViewById<ImageView>(R.id.circleImageView)
picture.setImageBitmap(bitmap)
}.addOnFailureListener{
finish()
}
}
private fun onClickListenerSearchUser(){
binding.btnSearchUsers.setOnClickListener{
startActivity(Intent(this,SearchUsers::class.java))
}
}
}
the header.xml in layout folder :
<?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="150dp"
android:id="@+id/header"
android:background="@color/Orange">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/circleImageView"
android:layout_width="67dp"
android:layout_height="67dp"
android:layout_marginStart="5dp"
app:civ_border_width="1dp"
android:src="@drawable/profile"
app:civ_border_color="@color/White"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.047"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.213" />
<TextView
android:id="@+id/tvFirstNameAndLastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="13dp"
android:text=""
android:textColor="@color/White"
android:textSize="15dp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/circleImageView" />
<TextView
android:id="@+id/tvPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text=""
android:textColor="@color/Black"
android:textSize="13dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvFirstNameAndLastName"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
the user.class that is for user profile information :
package af.azdreams.myconquer
data class User(var name : String ?= null, var lastName : String ?= null, var educationLevel : String ?= null, var province : String ?= null, var age : String ?= null, var phoneNumber : String ?= null)
please help me on this issue. thank you!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
