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

Android开发:如何实现将用户信息持久化展示在第二个Tab的列表中?

Got it, let's work through this problem together. You want two tabs: the first for inputting personal info, and the second to display all historical submissions (no data loss when switching tabs or restarting the app). It sounds like ListView didn't work out because you might have missed handling data persistence or dynamic updates properly. Let's fix this with a solid implementation using TabLayout, ViewPager2, RecyclerView, and shared preferences for persistence.

Step 1: Set Up the Main Tab Layout

First, create your main activity layout with TabLayout and ViewPager2 to manage the two tabs:

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

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Input Info"/>

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="History"/>
    </com.google.android.material.tabs.TabLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

Step 2: Implement Tab 1 (Input Fragment)

We'll expand your existing XML to add a submit button, then write the fragment logic to save data when submitted.

Tab 1 Layout (fragment_input.xml)

<?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">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="150dp"
            android:layout_height="50dp"
            android:text="Name"
            android:textColor="#9e3d7f"
            android:textSize="17sp"
            android:textStyle="bold"/>

        <EditText
            android:id="@+id/edittxt_name"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:hint="Enter your name"/>
    </LinearLayout>

    <!-- Add more input fields here (email, phone, etc.) if needed -->

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="32dp"
        android:text="Submit Info"/>
</LinearLayout>

Tab 1 Fragment Code (InputFragment.kt)

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.fragment.app.Fragment
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class InputFragment : Fragment() {
    private lateinit var etName: EditText
    private lateinit var btnSubmit: Button

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_input, container, false)
        etName = view.findViewById(R.id.edittxt_name)
        btnSubmit = view.findViewById(R.id.btn_submit)

        btnSubmit.setOnClickListener {
            val userName = etName.text.toString().trim()
            if (userName.isNotEmpty()) {
                saveUserInfo(userName)
                etName.text.clear()
                // Notify HistoryFragment to refresh data
                (activity as MainActivity).refreshHistory()
            }
        }

        return view
    }

    private fun saveUserInfo(name: String) {
        val sharedPref = requireActivity().getSharedPreferences("UserHistory", Context.MODE_PRIVATE)
        val gson = Gson()
        val existingList = getExistingUserList(sharedPref, gson)
        
        existingList.add(name)
        
        val editor = sharedPref.edit()
        editor.putString("users", gson.toJson(existingList))
        editor.apply()
    }

    private fun getExistingUserList(sharedPref: android.content.SharedPreferences, gson: Gson): MutableList<String> {
        val json = sharedPref.getString("users", null)
        return if (json != null) {
            val type = object : TypeToken<MutableList<String>>() {}.type
            gson.fromJson(json, type)
        } else {
            mutableListOf()
        }
    }
}

Step 3: Implement Tab 2 (History Fragment)

We'll use RecyclerView here (it's more flexible for dynamic updates than ListView) to display all historical entries.

Tab 2 Layout (fragment_history.xml)

<?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:padding="16dp">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_user_history"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

RecyclerView Adapter (UserHistoryAdapter.kt)

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class UserHistoryAdapter(private val userList: List<String>) : RecyclerView.Adapter<UserHistoryAdapter.UserViewHolder>() {

    class UserViewHolder(itemView: android.view.View) : RecyclerView.ViewHolder(itemView) {
        val tvUserName: TextView = itemView.findViewById(android.R.id.text1)
    }

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

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        holder.tvUserName.text = userList[position]
    }

    override fun getItemCount(): Int = userList.size
}

Tab 2 Fragment Code (HistoryFragment.kt)

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class HistoryFragment : Fragment() {
    private lateinit var rvHistory: RecyclerView
    private lateinit var adapter: UserHistoryAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_history, container, false)
        rvHistory = view.findViewById(R.id.rv_user_history)
        rvHistory.layoutManager = LinearLayoutManager(requireContext())
        loadHistoryData()
        return view
    }

    fun loadHistoryData() {
        val sharedPref = requireActivity().getSharedPreferences("UserHistory", Context.MODE_PRIVATE)
        val gson = Gson()
        val json = sharedPref.getString("users", null)
        val userList = if (json != null) {
            val type = object : TypeToken<MutableList<String>>() {}.type
            gson.fromJson(json, type)
        } else {
            mutableListOf()
        }
        adapter = UserHistoryAdapter(userList)
        rvHistory.adapter = adapter
    }
}

Step 4: Connect Tabs in Main Activity

Finally, set up the ViewPager2 adapter in your main activity to link the two fragments:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator

class MainActivity : AppCompatActivity() {
    private lateinit var viewPager: androidx.viewpager2.widget.ViewPager2
    private lateinit var historyFragment: HistoryFragment

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

        viewPager = findViewById(R.id.viewPager)
        val tabLayout = findViewById<com.google.android.material.tabs.TabLayout>(R.id.tabLayout)

        viewPager.adapter = object : FragmentStateAdapter(this) {
            override fun getItemCount(): Int = 2

            override fun createFragment(position: Int): androidx.fragment.app.Fragment {
                return when (position) {
                    0 -> InputFragment()
                    1 -> {
                        historyFragment = HistoryFragment()
                        historyFragment
                    }
                    else -> InputFragment()
                }
            }
        }

        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = when (position) {
                0 -> "Input Info"
                1 -> "History"
                else -> ""
            }
        }.attach()
    }

    // Call this to refresh history after submission
    fun refreshHistory() {
        historyFragment.loadHistoryData()
    }
}

Why This Works Better Than ListView

  • Data Persistence: We use SharedPreferences (with Gson to store lists) to save all submissions, so data stays even if the app restarts.
  • Dynamic Updates: The refreshHistory() method tells the HistoryFragment to reload data and update the RecyclerView immediately after submission.
  • Flexibility: RecyclerView is more efficient for dynamic lists and supports more customization than ListView.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:24:42