#kotlin #android-recyclerview #fragment
Вопрос:
Существует много ошибок в компоновке ресайклера. В частности, я думаю, что исключение nullpointrexception является самой большой ошибкой. Просмотрев несколько документов, я изменил onCreate в активности фрагмента на onViewCreated, и исключение nullpointrexception было решено. Однако произошла другая ошибка, и ошибка заключалась в том, что экземпляр свойства инициализации был инициализирован с опозданием.
это ошибка
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.notei, PID: 21857
kotlin.UninitializedPropertyAccessException: lateinit property instance has not been initialized
at com.example.myrecyclerview.App$Companion.getInstance(App.kt:7)
at com.example.myrecyclerview.MyViewHolder.bind(MyViewHolder.kt:40)
at com.example.myrecyclerview.MyRecyclerAdapter.onBindViewHolder(MyRecyclerAdapter.kt:39)
at com.example.myrecyclerview.MyRecyclerAdapter.onBindViewHolder(MyRecyclerAdapter.kt:11)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2792)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2319)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
и это приложение.kt
package com.example.myrecyclerview
import android.app.Application
class App: Application() {
companion object {
lateinit var instance: App
private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
а это MyViewHolder.kt
package com.example.myrecyclerview
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.notei.R
import kotlinx.android.synthetic.main.layout_recycler_item.view.*
// 커스텀 뷰홀더
class MyViewHolder(itemView: View,
recyclerviewInterface: MyRecyclerviewInterface):
RecyclerView.ViewHolder(itemView),
View.OnClickListener{
val TAG: String = "로그"
private val usernameTextView = itemView.user_name_txt
private val profileImageView = itemView.profile_img
private var myRecyclerviewInterface: MyRecyclerviewInterface? = null
//기본 생성자
init {
Log.d(TAG, "MyViewHolder - init() called")
itemView.setOnClickListener(this)
this.myRecyclerviewInterface = recyclerviewInterface
}
//데이터와 뷰를 묶는다.
fun bind(myModel: MyModel) {
Log.d(TAG, "MyViewHolder - bind() called")
// 텍스트뷰와 실제 텍스트 데이터를 묶는다.
usernameTextView.text = myModel.name
// 이미지뷰와 실제 이미지 데이터를 묶는다.
Glide
.with(App.instance)
.load(myModel.profileImage)
// .centerCrop()
.placeholder(R.mipmap.ic_launcher) //값이 없을 때
.into(profileImageView)
}
override fun onClick(v: View?) {
Log.d(TAG, "MyViewHolder - onClick() called")
this.myRecyclerviewInterface?.onItemClicked(adapterPosition)
}
}
and This is MyRecyclerAdapter.kt
package com.example.myrecyclerview
import android.content.ContentValues.TAG
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.notei.R
class MyRecyclerAdapter(myRecyclerviewInterface: MyRecyclerviewInterface): RecyclerView.Adapter<MyViewHolder>() {
val TAG: String = "로그"
private var modelList = ArrayList<MyModel>()
private var myRecyclerviewInterface: MyRecyclerviewInterface? = null
// 생성자
init {
this.myRecyclerviewInterface = myRecyclerviewInterface
}
// 뷰홀더가 생성 되었을때
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// 연결할 레이아웃 설정
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_recycler_item, parent, false), this.myRecyclerviewInterface!!)
}
// 목록의 아이템 수
override fun getItemCount(): Int {
return this.modelList.size
}
// 뷰와 뷰홀더가 묶였을 때(재활용되었을 때)
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
Log.d(TAG, "MyRecyclerAdapter - onBindVIewHolder() called / position: $position")
holder.bind(this.modelList[position])
}
// 외부에서 데이터 넘기기
fun submitList(modelList: ArrayList<MyModel>) {
this.modelList = modelList
}
}
and This is Fragment_1.kt
package com.example.notei
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myrecyclerview.MyModel
import com.example.myrecyclerview.MyRecyclerAdapter
import com.example.myrecyclerview.MyRecyclerviewInterface
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.fragment_1.*
class Fragment_1: Fragment(R.layout.fragment_1), MyRecyclerviewInterface {
val TAG: String = "로그"
//데이터 담을 배열
var modelList = ArrayList<MyModel>()
private lateinit var myRecyclerAdapter: MyRecyclerAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//recyclerview adapter
Log.d(TAG, "MainActivity - onCreate() called")
Log.d(TAG, "MainActivity - 반복문 돌리기 전 this.modelList.size : ${this.modelList.size}")
// 10번 반복
for (i in 1..10) {
val myModel = MyModel(name = "장인수 $i", profileImage = "https://edcan.kr/static/media/EDCAN_LOGO.2b1b47ce.svg")
this.modelList.add(myModel)
}
Log.d(TAG, "MainActivity - 반복문 돌린 후 this.modelList.size : ${this.modelList.size}")
// 어답터 인스턴스 생성
myRecyclerAdapter = MyRecyclerAdapter(this)
myRecyclerAdapter.submitList(this.modelList)
// 리사이클러뷰 설정
my_recycler_view.apply {
// 리사이클러뷰 방향 등 설정
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
// 어답터 장착
adapter = myRecyclerAdapter
}
}
override fun onItemClicked(position: Int) {
Log.d(TAG, "MainActivity - onItemClicked() called / position $position")
var name: String? = null
// 값이 비어있으면 ""를 넣는다.
// unwrapping - 언랩핑
val title: String = this.modelList[position].name ?: ""
//
// val title: String = name ?: "ㅎㅎ"
AlertDialog.Builder(requireContext())
.setTitle(title)
.setMessage("$title 의 코딩:")
.setPositiveButton("오케이") {
dialog, id -> Log.d(TAG, "MainActivity - 다이얼로그 확인 버튼 클릭했음")
}
.show()
}
}
and This is fragment_1.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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=".HomeActivity"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="@ id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
and This is layout_recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="20dp"
app:cardCornerRadius="20dp"
app:cardElevation="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="20dp">
<ImageView
android:id="@ id/profile_img"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"
/>
<TextView
android:id="@ id/user_name_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="장인수"
android:textSize="30sp"
android:layout_marginStart="20dp"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</androidx.cardview.widget.CardView>
)Для тех, кто в этом нуждается.
приложение/сборка.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions' //add
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //android 4.1 down:D
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.notei"
minSdkVersion 21
targetSdkVersion 30
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'
}
viewBinding {
enabled = true
}
}
dependencies {
// firebase add
implementation platform('com.google.firebase:firebase-bom:28.1.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-auth:21.0.1'
implementation 'com.google.firebase:firebase-firestore-ktx:23.0.1'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha04' //viewpager2
implementation 'androidx.legacy:legacy-support-v4:1.0.0'//viewpager2
implementation 'androidx.recyclerview:recyclerview:1.1.0' //recyclerview
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation 'com.google.android.material:material:1.3.0-alpha03' //Material Design
testImplementation 'junit:junit:4. '
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// imageView url 사용하기
implementation 'com.squareup.picasso:picasso:2.71828'
// 리사이클러뷰
implementation "androidx.recyclerview:recyclerview:1.2.0" //recyclerView
implementation "androidx.recyclerview:recyclerview-selection:1.1.0"//recyclerView
// 카트뷰
implementation "androidx.cardview:cardview:1.0.0" //cardview
// 글라이드 - 이미지 처리
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}
//add
// Task 'wrapper' not found in project ':app'. 라는 오류가 나와서 추가함 구글 검색해보니가 하라고 카더라
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
Я хочу, чтобы recyclerLayout был напечатан на fragment_1.xml
Огромное спасибо!
Комментарии:
1. В этом случае вы должны использовать
view.context
с Glide, а неApp.instance
2. Не могли бы вы сказать мне конкретно?
3. Что касается ошибки, вы забыли указать приложение в качестве класса приложения в манифесте?