解决Kotlin项目中lateinit属性binding未初始化的崩溃问题
解决ViewBinding未初始化导致的运行时崩溃
崩溃日志
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bugunneyesem/com.example.bugunneyesem.TariflerPageUser}: kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
相关代码
TariflerPageUser Activity代码
class TariflerPageUser : AppCompatActivity() { lateinit var binding: ActivityTariflerPageUserBinding private lateinit var firebaseAuth: FirebaseAuth private lateinit var kategoriArrayList: ArrayList<ModelKategori> private lateinit var viewPagerAdapter: ViewPagerAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) firebaseAuth = FirebaseAuth.getInstance() binding = ActivityTariflerPageUserBinding.inflate(layoutInflater) setupWithViewPagerAdapter(binding.viewPager) binding.tabLayout.setupWithViewPager(binding.viewPager) binding.backBtn.setOnClickListener{ startActivity(Intent(this,ManiAnasayfa::class.java)) } binding.fabBtn.setOnClickListener{ startActivity(Intent(this,TarifEkleAdmin::class.java)) } } private fun setupWithViewPagerAdapter(viewPager: ViewPager){ viewPagerAdapter = ViewPagerAdapter(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, this) kategoriArrayList = ArrayList() //veri tabanından kategorileri yükleme val ref = FirebaseDatabase.getInstance().getReference("Kategoriler") ref.addListenerForSingleValueEvent(object : ValueEventListener{ override fun onDataChange(snapshot: DataSnapshot) { kategoriArrayList.clear() val modelAll = ModelKategori("01", "Hepsi", 1, "") val modelMostViewed = ModelKategori("01", "En Çok Görüntülenen", 1, "") kategoriArrayList.add(modelAll) kategoriArrayList.add(modelMostViewed) //viewPagerAdapter'a ekleme yeni kategori eklerken burayada eklenmeli viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${modelAll.id}", "${modelAll.kategori}", "${modelAll.uid}" ), modelAll.kategori ) viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${modelMostViewed.id}", "${modelMostViewed.kategori}", "${modelMostViewed.uid}" ), modelMostViewed.kategori ) //refresh list viewPagerAdapter.notifyDataSetChanged() //firebase db den load diğer kategoriler için for(ds in snapshot.children){ //get data val model = ds.getValue(ModelKategori::class.java) kategoriArrayList.add(model!!) //viewPagerAdapter a ekleme viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${model.id}", "${model.kategori}", "${model.uid}" ), model.kategori ) viewPagerAdapter.notifyDataSetChanged() } } override fun onCancelled(error: DatabaseError) { Toast.makeText(applicationContext,"SetupWithPageAdapter hata", Toast.LENGTH_LONG).show() } }) //setup adapter to viewpager viewPager.adapter = viewPagerAdapter } class ViewPagerAdapter(fm: FragmentManager, behavior: Int, context: Context): FragmentPagerAdapter(fm, behavior){ private val fragmentsList: ArrayList<FoodsUserFragment> = ArrayList() //kategori başlıklarının listesi for tab private val fragmentTitleList: ArrayList<String> = ArrayList() private val context: Context init { this.context = context } override fun getCount(): Int { return fragmentsList.size } override fun getItem(position: Int): Fragment { return fragmentsList[position] } override fun getPageTitle(position: Int): CharSequence { return fragmentTitleList[position] } public fun addFragment(fragment: FoodsUserFragment, title: String){ fragmentsList.add(fragment) fragmentTitleList.add(title) } } }
app模块build.gradle代码
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'com.google.gms.google-services' android { namespace 'com.example.bugunneyesem' compileSdk 34 defaultConfig { applicationId "com.example.bugunneyesem" minSdk 23 targetSdk 32 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 JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures{ viewBinding true } } def lottieVersion = '6.2.0' dependencies { implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' //2.1.4 implementation 'androidx.navigation:navigation-fragment-ktx:2.7.5' implementation 'androidx.navigation:navigation-ui-ktx:2.7.5' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2' implementation 'com.google.firebase:firebase-storage:20.3.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' implementation "com.airbnb.android:lottie:$lottieVersion" implementation 'com.google.firebase:firebase-firestore:24.10.0' implementation 'com.google.firebase:firebase-database:20.3.0' implementation 'com.google.firebase:firebase-core:21.1.1' implementation 'com.google.firebase:firebase-auth:20.0.0' implementation 'androidx.work:work-runtime-ktx:2.9.0' //2.7.1 implementation 'com.squareup.picasso:picasso:2.8' }
问题原因与修复方案
问题原因
崩溃核心是**lateinit修饰的binding变量在未初始化时就被调用**:onCreate方法里先执行了setContentView(binding.root),此时binding还没有被赋值,直接触发UninitializedPropertyAccessException。
修复步骤
调整onCreate方法的代码顺序,先初始化binding,再设置ContentView:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 先初始化binding binding = ActivityTariflerPageUserBinding.inflate(layoutInflater) // 再设置布局 setContentView(binding.root) firebaseAuth = FirebaseAuth.getInstance() setupWithViewPagerAdapter(binding.viewPager) binding.tabLayout.setupWithViewPager(binding.viewPager) binding.backBtn.setOnClickListener{ startActivity(Intent(this,ManiAnasayfa::class.java)) } binding.fabBtn.setOnClickListener{ startActivity(Intent(this,TarifEkleAdmin::class.java)) } }
额外优化建议
Firebase回调中频繁调用notifyDataSetChanged()会导致UI频繁刷新,建议将刷新操作移到所有分类添加完成后执行:
override fun onDataChange(snapshot: DataSnapshot) { kategoriArrayList.clear() val modelAll = ModelKategori("01", "Hepsi", 1, "") val modelMostViewed = ModelKategori("01", "En Çok Görüntülenen", 1, "") kategoriArrayList.add(modelAll) kategoriArrayList.add(modelMostViewed) viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${modelAll.id}", "${modelAll.kategori}", "${modelAll.uid}" ), modelAll.kategori ) viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${modelMostViewed.id}", "${modelMostViewed.kategori}", "${modelMostViewed.uid}" ), modelMostViewed.kategori ) //firebase db den load diğer kategoriler için for(ds in snapshot.children){ val model = ds.getValue(ModelKategori::class.java) kategoriArrayList.add(model!!) viewPagerAdapter.addFragment( FoodsUserFragment.newInstance( "${model.id}", "${model.kategori}", "${model.uid}" ), model.kategori ) } // 所有分类添加完成后统一刷新UI viewPagerAdapter.notifyDataSetChanged() }
内容的提问来源于stack exchange,提问作者noneleft
相关产品推荐
相关产品推荐

