web-dev-qa-db-ja.com

kotlin.UninitializedPropertyAccessException:lateinitプロパティroomClickedInterfaceが初期化されていません

プッシャーチャットキットのチュートリアルに従って "KOTLINとプッシャーチャットキットを使用してグループチャットアプリを構築する" を実行しようとしていますが、リサイクラービューアダプターで問題が発生しています。参考までに、私はまだKotlinを学んでいます。私はlateinit変数を読んでいますが、このケースに対処するものは何も見つかりません。エラーは、リサイクラービューアダプターで発生します。

これは私が得るエラーです:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.Android_myneighborsbookshelf, PID: 26692
    kotlin.UninitializedPropertyAccessException: lateinit property roomClickedInterface has not been initialized
        at com.example.Android_myneighborsbookshelf.adapters.ChatRoomsListAdapter.getRoomClickedInterface(ChatRoomsListAdapter.kt:13)
        at com.example.Android_myneighborsbookshelf.adapters.ChatRoomsListAdapter$ViewHolder.onClick(ChatRoomsListAdapter.kt:66)
        at Android.view.View.performClick(View.Java:6597)
        at Android.view.View.performClickInternal(View.Java:6574)
        at Android.view.View.access$3100(View.Java:778)
        at Android.view.View$PerformClick.run(View.Java:25885)
        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)

ChatRoomsListActivity.kt

class ChatRoomsListActivity : AppCompatActivity() {
    val adapter = ChatRoomsListAdapter();

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat_room_list)
        initRecyclerView()
        initChatManager()
    }

    private fun initRecyclerView() {
        recycler_view.layoutManager = LinearLayoutManager(this@ChatRoomsListActivity)
        recycler_view.adapter = adapter
    }

    private fun initChatManager() {
        val chatManager = ChatManager(
                instanceLocator = "blahblahblah",
                userId = "username1-PCKid",
                dependencies = AndroidChatkitDependencies(
                        tokenProvider = ChatkitTokenProvider(
                                endpoint = "blahblahblah",
//                                endpoint = "http://10.0.2.2:3000/auth",
                                userId = "username1-PCKid"
                        )
                )
        )

        chatManager.connect(listeners = ChatListeners(
                onErrorOccurred = { },
                onAddedToRoom = { },
                onRemovedFromRoom = { },
                onCurrentUserReceived = { },
                onNewReadCursor = { },
                onRoomDeleted = { },
                onRoomUpdated = { },
                onPresenceChanged = { u, n, p -> },
                onUserJoinedRoom = { u, r -> },
                onUserLeftRoom = { u, r -> },
                onUserStartedTyping = { u, r -> },
                onUserStoppedTyping = { u, r -> }
        )) { result ->
            when (result) {
                is Result.Success -> {
                    // We have connected!
                    val currentUser = result.value
                    AppController.currentUser = currentUser
                    val userJoinedRooms = ArrayList<Room>(currentUser.rooms)
                    for (i in 0 until userJoinedRooms.size) {
                        adapter.addRoom(userJoinedRooms[i])
                    }

                    currentUser.getJoinableRooms { result ->
                        when (result) {
                            is Result.Success -> {
                                // Do something with List<Room>
                                val rooms = result.value
                                runOnUiThread {
                                    for (i in 0 until rooms.size) {
                                        adapter.addRoom(rooms[i])
                                    }
                                }
                            }
                        }
                    }

                    adapter.setInterface(object : ChatRoomsListAdapter.RoomClickedInterface {
                        override fun roomSelected(room: Room) {
                            if (room.memberUserIds.contains(currentUser.id)) {
                                // user already belongs to this room
                                roomJoined(room)
                            } else {
                                currentUser.joinRoom(
                                        roomId = room.id,
                                        callback = { result ->
                                            when (result) {
                                                is Result.Success -> {
                                                    // Joined the room!
                                                    roomJoined(result.value)
                                                }
                                                is Result.Failure -> {
                                                    Log.d("TAG", result.error.toString())
                                                }
                                            }
                                        }
                                )
                            }
                        }
                    })
                }

                is Result.Failure -> {
                    // Failure
                    Log.d("TAG", result.error.toString())
                }
            }
        }
    }

    private fun roomJoined(room: Room) {
        val intent = Intent(this@ChatRoomsListActivity, ChatRoomsListActivity::class.Java)
        intent.putExtra("room_id", room.id)
        intent.putExtra("room_name", room.name)
        startActivity(intent)
    }
}

RecyclerView Adapter

import Android.view.View
import Android.view.ViewGroup
import Android.widget.TextView
import com.pusher.chatkit.rooms.Room
import Android.view.LayoutInflater
import androidx.recyclerview.widget.RecyclerView
import com.example.Android_myneighborsbookshelf.R

class ChatRoomsListAdapter: RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {
    private var list = ArrayList<Room>()
    lateinit var roomClickedInterface:RoomClickedInterface // <-- Error occurs here - kt.13

    fun addRoom(room:Room){
        list.add(room)
        notifyDataSetChanged()
    }

    fun setInterface(roomClickedInterface:RoomClickedInterface){
        this.roomClickedInterface = roomClickedInterface
    }

    override fun getItemCount(): Int {
        return list.size
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
                .inflate(
                        Android.R.layout.simple_list_item_1,
                        parent,
                        false
                )

        return ViewHolder(view)
    }


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.roomName.text = list[position].name

    }

    inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView), View.OnClickListener {
        override fun onClick(p0: View?) {
            roomClickedInterface.roomSelected(list[adapterPosition]) // <-- Error occurs here kt.66
        }

        var roomName: TextView = itemView.findViewById(Android.R.id.text1)

        init {
            itemView.setOnClickListener(this)
        }
    }

    interface RoomClickedInterface{
        fun roomSelected(room:Room)
    }
}

ありとあらゆる助けをいただければ幸いです。

2
Cflux

lateinitは初期化が遅いことを意味します。コンストラクターで変数を初期化したくない場合は、後で初期化する必要があります。可能であれば使用する前に初期化を保証します、その変数をlateinitで宣言します。キーワード。初期化されるまでメモリは割り当てられません。

したがって、使用する前にlateinitプロパティを初期化する必要があります。

オプション-1:リスト項目をクリックする前に、setInterface()を呼び出してプロパティを初期化します。以下のように、.isInitializedを使用して、lateinit変数がすでに初期化されているかどうかを確認することもできます。

override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}

オプション-2:アダプタからlateinitプロパティを削除し、セッターも削除します

//lateinit var roomClickedInterface:RoomClickedInterface

そして、アダプターのコンストラクターのパラメーターとしてRoomClickedInterfaceを渡します

class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}

オプション-3:lateinitを削除し、nullableプロパティを使用します

private var roomClickedInterface: RoomClickedInterface? = null

次に、null安全表記?.を使用して以下のように使用します。

override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}
3
Md. Asaduzzaman