kotlin .UninitializedPropertyAccessException: свойство lateinit roomClickedInterface не было инициализировано - PullRequest
2 голосов
/ 07 января 2020

Я пытаюсь следовать учебному пособию Pusher Chatkit для "СОЗДАНИЕ ПРИЛОЖЕНИЯ ДЛЯ ЧАТА ГРУППЫ С ИСПОЛЬЗОВАНИЕМ KOTLIN И PUSHER CHATKIT" , однако возникла проблема с адаптером Recycler View. К вашему сведению, я все еще учусь Kotlin. Я читал про латинитные переменные, но не могу найти ничего, что касалось этого случая. Ошибка происходит в адаптере представления переработчика.

Это ошибка, которую я получаю:

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

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)
    }
}

Любая и вся помощь приветствуется.

1 Ответ

3 голосов
/ 07 января 2020

lateinit означает позднюю инициализацию. Если вы не хотите инициализировать переменную в конструкторе, вместо этого вы хотите инициализировать ее позже и, если вы можете гарантировать инициализацию перед ее использованием , то объявите эту переменную с ключевым словом lateinit. Он не будет выделять память до инициализации.

Итак, вам необходимо инициализировать свойство lateinit, прежде чем пытаться его использовать.

Опция - 1: Вызовите setInterface(), чтобы инициализировать свойство, прежде чем щелкнуть элемент списка. Вы также можете проверить, была ли lateinit var уже инициализирована или не используется .isInitialized, как показано ниже:

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])
}
...