You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin异步加载RecyclerView数组数据源的实现方案咨询

Hey there! Let's figure out how to fix that RecyclerView lag by loading your content asynchronously. First, even though your current list() method just returns resource IDs, scaling up the number of items can still block the main thread (especially if you're loading those resources directly in the adapter later). Here are the best Kotlin-based solutions tailored to your case:


1. Use Kotlin Coroutines + ViewModel (Android Official Recommendation)

Coroutines make async code feel like sync code, and pairing them with ViewModel prevents memory leaks and preserves data during configuration changes (like screen rotations).

Step 1: Add Coroutines Dependencies

First, make sure you have these in your app-level build.gradle.kts (or build.gradle):

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
}

Step 2: Refactor ContentList for Async

Your list() method is lightweight now, but wrapping it in a suspend function with a background dispatcher makes it future-proof (if you later switch to loading from files/databases):

class ContentList {
    // Suspend function runs in background thread
    suspend fun list(title: String): Array<Array<Int>> = withContext(Dispatchers.Default) {
        return@withContext when(title) {
            "Hijaiyyah Letters" -> arrayOf(
                arrayOf(R.drawable.ic_intro1_1, R.raw.ahem_x),
                arrayOf(R.drawable.ic_intro1_2, R.raw.bad_disk_x),
                // ... all your Hijaiyyah entries here
            )
            "Fat-hah Vowel 1" -> arrayOf(
                arrayOf(R.drawable.ic_fathah1_1, R.raw.ahem_x),
                arrayOf(R.drawable.ic_fathah1_2, R.raw.bad_disk_x),
                // ... all your Fat-hah entries here
            )
            else -> arrayOf(
                arrayOf(R.drawable.ic_tbr, R.raw.ahem_x),
                arrayOf(R.drawable.ic_tbr, R.raw.bad_disk_x),
                // ... default entries here
            )
        }
    }
}

Step 3: Create a ViewModel to Manage Async Loading

ViewModel handles the async task and holds your data safely:

class ContentViewModel : ViewModel() {
    private val contentList = ContentList()
    private val _contentData = MutableLiveData<Array<Array<Int>>>()
    // Expose immutable LiveData to the UI
    val contentData: LiveData<Array<Array<Int>>> = _contentData

    fun loadContent(title: String) {
        // ViewModelScope automatically cancels tasks when ViewModel is destroyed
        viewModelScope.launch {
            val data = contentList.list(title)
            // Post data to main thread to update UI
            _contentData.postValue(data)
        }
    }
}

Step 4: Observe Data in Your Activity/Fragment

Connect the ViewModel to your RecyclerView and update the UI when data is ready:

class YourContentActivity : AppCompatActivity() {
    private lateinit var viewModel: ContentViewModel
    private lateinit var recyclerViewAdapter: YourRecyclerViewAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_content)

        // Initialize ViewModel and Adapter
        viewModel = ViewModelProvider(this)[ContentViewModel::class.java]
        recyclerViewAdapter = YourRecyclerViewAdapter(emptyArray())
        your_recycler_view.adapter = recyclerViewAdapter

        // Show loading state here (e.g., a ProgressBar)

        // Observe data changes and update adapter
        viewModel.contentData.observe(this) { contentArray ->
            recyclerViewAdapter.updateData(contentArray)
            // Hide loading state here
        }

        // Trigger data loading (replace with your actual navBarTitle)
        val navBarTitle = "Hijaiyyah Letters"
        viewModel.loadContent(navBarTitle)
    }
}

Step 5: Fix the Real Cause of Lag - Async Resource Loading

Most likely, your lag comes from loading Drawables/Raw resources directly in the adapter's onBindViewHolder. Fix this by loading resources asynchronously:

class YourRecyclerViewAdapter(private var contentData: Array<Array<Int>>) :
    RecyclerView.Adapter<YourRecyclerViewAdapter.ContentViewHolder>() {

    fun updateData(newData: Array<Array<Int>>) {
        contentData = newData
        // Use DiffUtil instead of notifyDataSetChanged() for better performance!
        notifyDataSetChanged()
    }

    inner class ContentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val itemImage: ImageView = itemView.findViewById(R.id.item_image)
    }

    override fun onBindViewHolder(holder: ContentViewHolder, position: Int) {
        val (drawableId, rawId) = contentData[position]

        // Use Glide to load Drawable asynchronously (add Glide dependency if needed)
        Glide.with(holder.itemImage.context)
            .load(drawableId)
            .into(holder.itemImage)

        // For audio resources, load them in background thread
        holder.itemView.lifecycleScope.launch {
            val audioStream = withContext(Dispatchers.IO) {
                holder.itemView.context.resources.openRawResource(rawId)
            }
            // Store the stream for later use (e.g., play button click)
        }
    }

    // Implement onCreateViewHolder and getItemCount as usual
}

2. Extra Performance Tips

  • Use DiffUtil: Replace notifyDataSetChanged() with DiffUtil to only update changed items, reducing unnecessary UI refreshes.
  • Pagination: If your content list gets extremely large, load items in chunks (e.g., 20 at a time) instead of all at once.
  • Cache Resources: Preload frequently used Drawables/Audio in a background thread when your app starts, so they're ready when needed.

内容的提问来源于stack exchange,提问作者Joe Shamuraq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:15:49