从套接字收到的值推送到RecyclerView

时间:2019-07-12 20:02:44

标签: android kotlin android-recyclerview

我有以下与RecyclerView配合使用的代码,同时,我有一个websocket适用于onMessage的代码,并正确打印了接收到的味精。 / p>

然后,我尝试将它们合并在一起,即从socket接收数据并将其直接推送到RecyclerView,但是在RecyclerView屏幕上没有显示任何内容

在我的一项试验中,出现了此错误:

  

I / Websocket:错误仅创建视图的原始线程   层次结构可以触摸其视图。

lateinit var mWebSocketClient: WebSocketClient
lateinit var uniqueID: String
lateinit var rv: RecyclerView

val chaptersList: ArrayList<String> = ArrayList()

class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        rv = rvChapterList    //  "@+id/rvChapterList" of RecyclerView

         // chaptersList.add(s)
         //   rvChapterList.layoutManager = layoutManager
         //   rvChapterList.adapter = ChapterAdapter(this, chaptersList)
        var context= this
        connectWebSocket(context)
}


fun connectWebSocket(context: MainActivity) {
    val uri: URI
    try {
        uri = URI("ws://10.0.2.2:8080/ws")
    } catch (e: URISyntaxException) {
        e.printStackTrace()
        println("ws faild")
        return
    }

    mWebSocketClient = object : WebSocketClient(uri) {
        override fun onOpen(serverHandshake: ServerHandshake) {
            Log.i("Websocket", "Opened")
            mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL)
        }

        override fun onMessage(s: String) {
            Log.i("Websocket", "Recieved $s")  // This is working
            chaptersList.add(s)
            Log.i("chaptersList", "chaptersList $s")  // This is working

            rv.layoutManager = LinearLayoutManager(context)
            rv.adapter = ChapterAdapter(context , chaptersList)  // This is not working

        }
    }
    mWebSocketClient.connect()
}

更新

参考this的答案,我尝试了以下操作,但没有成功:

lateinit var rv: RecyclerView
lateinit var layoutManager: RecyclerView.LayoutManager
lateinit var adaptor: ChapterAdapter

class MainActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
            layoutManager = LinearLayoutManager(this)
            rv = rvChapterList
            adaptor = ChapterAdapter(this, chaptersList)
           rv.adapter = adaptor
           rv.layoutManager = layoutManager
           rv.adapter = ChapterAdapter(this, chaptersList)
    }
}

fun connectWebSocket(context: MainActivity) {
   override fun onMessage(s: String) {
            val insertIndex = chaptersList.size
            chaptersList.add(insertIndex, s)
            adaptor.notifyItemInserted(insertIndex)

            adaptor.notifyDataSetChanged()
   }
}

1 个答案:

答案 0 :(得分:3)

只能在主线程中访问视图。由于onMessage()方法是在 worker线程(后台)上运行的,因此无法直接在视图上进行更改。有多种方法可以从{em> worker thread 中更改视图,例如androd.os.Handler。在您的情况下,runOnUiThread(Runnable)提供的Activity.class方法是一个不错的选择。它以runnable作为参数,并在UI线程上运行。就您而言,它可以按以下方式使用:

override fun onMessage(s: String) {
    val insertIndex = chaptersList.size
    chaptersList.add(insertIndex, s)

    Thread {
        runOnUiThread {
            adaptor.notifyItemInserted(insertIndex)  
        }
    }.run()
}

更新: 另一种更可靠的方法是使用LiveData中的Android Architecture Components。由于LiveData是一个可观察且具有生命周期意识的数据持有者类,因此可以这样使用:

另一个类文件:

class SocketClient {
    val message = MutableLiveData<String>()

    fun connectWebSocket(context: Context) {
        // Setup stuff

        mWebSocketClient = object : WebSocketClient(uri) {
            override fun onOpen(serverHandshake: ServerHandshake) {
                // Opened do some stuff
            }

            override fun onMessage(s: String) {
                message.postValue(s)
            }
        }
        mWebSocketClient.connect()
    }
}

在活动的onCreate()中:

val client = SocketClient()

client.message.observe(this, Observer { s: String ->
    val insertIndex = chaptersList.size
    chaptersList.add(insertIndex, s)
    adaptor.notifyItemInserted(insertIndex)
})

client.connectWebSocket(this)

在使用LiveData之前,需要添加依赖项。参见official documentation。 为:

    def lifecycle_version = "2.0.0"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"