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

Android:如何在ViewPager中容纳1000个动态Fragment?

Fixing the 1000-Question ViewPager Issue (No More Failed Fragment Loads)

Ah, I get it—you tried using ViewPager with 1000 Fragments for your questions, and it crashed or wouldn't load. That makes total sense because each Fragment is a separate object, and 1000 of them will gobble up way too much memory—the system will either kill your app or refuse to instantiate that many. Let's go through the best solutions to handle this scale efficiently.

Why Your Original Approach Failed

The default ViewPager (with FragmentPagerAdapter) keeps every Fragment you create in memory permanently. Even if you crank up offscreenPageLimit, you're still asking the system to hold hundreds of Fragment instances at once—this is a non-starter for 1000 items.

Best Solution: ViewPager2 + View Reuse (No Fragments Needed)

ViewPager2 is built on RecyclerView, which means it supports view recycling out of the box. Instead of creating a Fragment per question, we'll reuse a single layout template for all questions. This is way more memory-efficient and fast.

Step 1: Define Your Question Data Class

First, create a data class to hold each question's details:

data class Question(
    val id: Int,
    val title: String,
    val options: List<String>,
    val correctAnswer: Int,
    var userAnswer: Int? = null // Track user's selection
)

Step 2: Create a Reusable Question Item Layout

Make an item_question.xml layout for your question + 4 options (use a RadioGroup for single-choice):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_question_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:marginBottom="16dp"/>

    <RadioGroup
        android:id="@+id/rg_options"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"/>

</LinearLayout>

Step 3: Build a RecyclerView Adapter for ViewPager2

This adapter will inflate the item layout once, then reuse it for every question:

class QuestionAdapter(private val questions: List<Question>) : RecyclerView.Adapter<QuestionAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvTitle: TextView = itemView.findViewById(R.id.tv_question_title)
        val rgOptions: RadioGroup = itemView.findViewById(R.id.rg_options)
    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val question = questions[position]
        
        // Bind question title
        holder.tvTitle.text = question.title
        
        // Clear existing options (critical for recycling)
        holder.rgOptions.removeAllViews()
        
        // Add 4 options to the RadioGroup
        question.options.forEachIndexed { index, optionText ->
            val radioButton = RadioButton(holder.rgOptions.context).apply {
                text = optionText
                id = index
                isChecked = (index == question.userAnswer) // Restore user's selection
            }
            holder.rgOptions.addView(radioButton)
        }
        
        // Save user's selection when they choose an option
        holder.rgOptions.setOnCheckedChangeListener { _, checkedId ->
            question.userAnswer = checkedId
        }
    }

    override fun getItemCount() = questions.size
}

Step 4: Set Up ViewPager2 in Your Activity

Initialize ViewPager2 and attach the adapter:

class QuestionActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_question)
        
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager2)
        
        // Generate 1000 sample questions (replace with your real data)
        val questions = List(1000) { index ->
            Question(
                id = index + 1,
                title = "Question ${index + 1}: Which of the following is correct?",
                options = listOf("Option A", "Option B", "Option C", "Option D"),
                correctAnswer = (0..3).random()
            )
        }
        
        viewPager2.adapter = QuestionAdapter(questions)
    }
}

Alternative: If You Must Use Fragments

If you have a specific need to use Fragments (e.g., complex per-question logic), use FragmentStateAdapter with ViewPager2. This adapter destroys Fragments that are off-screen and only saves their state, which is much more memory-friendly than FragmentPagerAdapter.

Example FragmentStateAdapter

class QuestionFragmentAdapter(activity: FragmentActivity, private val questions: List<Question>) : FragmentStateAdapter(activity) {
    override fun getItemCount() = questions.size

    override fun createFragment(position: Int): Fragment {
        return QuestionFragment.newInstance(questions[position])
    }
}

// Your QuestionFragment class
class QuestionFragment : Fragment() {
    companion object {
        private const val ARG_QUESTION = "question"
        fun newInstance(question: Question): QuestionFragment {
            val args = Bundle().apply {
                putParcelable(ARG_QUESTION, question)
            }
            return QuestionFragment().apply { arguments = args }
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_question, container, false)
        val question = arguments?.getParcelable<Question>(ARG_QUESTION) ?: return view
        
        // Bind data to your Fragment's views here
        return view
    }
}

Important Note: State Preservation

Whichever approach you choose, make sure to save the user's answers when the app is rotated or backgrounded. Use a ViewModel (with SavedStateHandle if needed) to persist the userAnswer values across configuration changes.

内容的提问来源于stack exchange,提问作者raguM.tech.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:23:59