使用从 HandlerThread 继承的类时,Handler/Looper 出现问题,handleMessage 的代码不运行

问题描述

我的项目中有一个片段:

private const val TAG = "PhotogalleryFragment"

class PhotogalleryFragment: Fragment() {
  private lateinit var photoRecyclerView: RecyclerView
  private lateinit var photogalleryviewmodel: Photogalleryviewmodel
  private lateinit var thumbnailDownloader: ThumbnailDownloader<PhotoHolder>

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    retainInstance = true
    photogalleryviewmodel = viewmodelProvider(this).get(Photogalleryviewmodel::class.java)

    thumbnailDownloader = ThumbnailDownloader()
    lifecycle.addobserver(thumbnailDownloader)
  }

  override fun onCreateView (inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View?
  {
    val view = inflater.inflate(R.layout.fragment_photo_gallery,container,false)

    photoRecyclerView = view.findViewById(R.id.photo_recycler_view)
    photoRecyclerView.layoutManager = GridLayoutManager(context,3)

    return view
  }

  override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
    super.onViewCreated(view,savedInstanceState)

    photogalleryviewmodel.galleryItemLiveData.observe(viewLifecycleOwner,Observer { galleryItems ->
        photoRecyclerView.adapter = PhotoAdapter(galleryItems)
      }
    )
  }

  private class PhotoHolder(imageView: ImageView) : RecyclerView.ViewHolder(imageView) {
    val bindDrawable: (Drawable) -> Unit = imageView::setimageDrawable
  }

  private inner class PhotoAdapter(private val galleryItems: List<galleryItem>):
    RecyclerView.Adapter<PhotoHolder>()
  {
    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): PhotoHolder
    {
      val view = layoutInflater.inflate(R.layout.list_item_gallery,parent,false)
          as ImageView
      return PhotoHolder(view)
    }

    override fun getItemCount(): Int = galleryItems.size

    override fun onBindViewHolder(holder: PhotoHolder,position: Int) {
      val galleryItem = galleryItems[position]
      val placeholder: Drawable = ContextCompat.getDrawable(requireContext(),R.drawable.bill_up_close) ?: ColorDrawable()
      holder.bindDrawable(placeholder)
      thumbnailDownloader.queueThumbnail(holder,galleryItem.url)
    }
  }

  override fun onDestroy() {
    super.onDestroy()
    lifecycle.removeObserver(thumbnailDownloader)
  }

  companion object {
    fun newInstance() = PhotogalleryFragment()
  }
}

而且我还有一个类可以在后台线程中从 Flickr 下载缩略图

private const val TAG = "ThumbnailDownloader"
private const val MESSAGE_DOWNLOAD = 0

class ThumbnailDownloader<in T> : HandlerThread(TAG),LifecycleObserver {
  private var hasQuit = false
  private lateinit var requestHandler: Handler
  private val requestMap = ConcurrentHashMap<T,String>()
  private val flickr = Flickr(ApiSingleton.get().flickr)

  override fun quit(): Boolean {
    hasQuit = true
    return super.quit()
  }

  fun queueThumbnail (target: T,url: String) {
    Log.i (TAG,"Got a url: $url")
    requestMap[target] = url
    requestHandler = Handler()
    requestHandler.obtainMessage(MESSAGE_DOWNLOAD,target).sendToTarget()
  }

  @Suppress("UNCHECKED_CAST")
  @SuppressLint("HandlerLeak")
  override fun onLooperPrepared() {
    requestHandler = object : Handler() {
      override fun handleMessage(msg: Message) {
        if (msg.what == MESSAGE_DOWNLOAD) {
          val target = msg.obj as T
          Log.i (TAG,"Got a request for URL: ${requestMap[target]}")
          handleRequest(target)
        }
      }
    }
  }

  private fun handleRequest(target: T) {
    val url = requestMap[target] ?: return
    val bitmap = flickr.fetchPhoto(url) ?: return
  }

  @OnLifecycleEvent (Lifecycle.Event.ON_CREATE)
  fun setup() {
    Log.i (TAG,"Starting background thread")
  }

  @OnLifecycleEvent (Lifecycle.Event.ON_DESTROY)
  fun tearDown() {
    Log.i (TAG,"Destroying background thread")
  }
}

当我启动我的程序时,我有以下日志:

I/ThumbnailDownloader: Starting background thread
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
...
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg

但我打算再写一个日志:

I/ThumbnailDownloader: Starting background thread
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
I/ThumbnailDownloader: Got a request for URL: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
...
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg
I/ThumbnailDownloader: Got a request for URL: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg

override fun handleMessage(msg: Message)代码未执行。 也许这是因为行requestHandler = Handler(),其中 Handler() 被划掉了, Android Studio 表示已弃用。

我需要做什么来运行 handleMessage 代码?也许我需要用 Looper 做点什么 后台线程,我不知道。感谢您的回答!

解决方法

我忘记了:

  1. 将looper添加到{ token: { kind: "identitytoolkit#VerifyPasswordResponse",email: "myEmail@gmail.com",displayName: "myName",idToken: "generatedToken",registered: true },message: "successfully created user profile" } 中的Handler()构造函数
  2. onLooperPrepared()中添加start(),在fun setup()中添加quit()
  3. 并且代码行 fun tearDown() 过多。

我看了一部简单解释了 HandlerThread、Handler 和 Looper 的小电影后就猜到了这一切。

问题已解决。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...