Android Studio如何基于日期实现动态Fragment,用ViewPager筛选Room数据
实现方案整体流程
1. 前置处理:Room日期字段统一格式化
先确保表中日期字段支持高效范围查询,推荐存储毫秒时间戳或者固定格式的日期字符串,实体类参考示例:
@Entity(tableName = "business_data") data class BusinessData( @PrimaryKey(autoGenerate = true) val id: Int = 0, val content: String, // 存储毫秒时间戳,方便范围计算 val dateTimestamp: Long, // 可选冗余字段,格式固定为yyyy-MM-dd,简化特殊场景查询 val dateStr: String )
2. 封装通用筛选Fragment
日/月/年维度的Fragment仅筛选条件不同,逻辑完全一致,直接封装可复用的通用Fragment,通过Bundle传递筛选参数:
class DateFilterFragment : Fragment() { companion object { private const val ARG_START_TIMESTAMP = "start_ts" private const val ARG_END_TIMESTAMP = "end_ts" fun newInstance(startTs: Long, endTs: Long): DateFilterFragment { val fragment = DateFilterFragment() val args = Bundle() args.putLong(ARG_START_TIMESTAMP, startTs) args.putLong(ARG_END_TIMESTAMP, endTs) fragment.arguments = args return fragment } } private lateinit var viewModel: BusinessViewModel private lateinit var dataAdapter: BusinessDataAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_date_filter, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化列表和ViewModel dataAdapter = BusinessDataAdapter() binding.recyclerView.adapter = dataAdapter viewModel = ViewModelProvider(this)[BusinessViewModel::class.java] // 获取传入的时间范围参数 val startTs = arguments?.getLong(ARG_START_TIMESTAMP) ?: 0 val endTs = arguments?.getLong(ARG_END_TIMESTAMP) ?: 0 // 查询对应范围的数据并渲染 viewModel.getDataByTimeRange(startTs, endTs).observe(viewLifecycleOwner) { dataAdapter.submitList(it) } } }
3. ViewPager + TabLayout 配置
3.1 布局引入
在承载页的XML布局中添加TabLayout和ViewPager,推荐使用官方更推荐的ViewPager2:
<LinearLayout 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="scrollable" /> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
3.2 PagerAdapter实现
// 标签数据类,存储标签名和对应时间范围 data class TabItem(val title: String, val startTs: Long, val endTs: Long) class FilterPagerAdapter(fragmentActivity: FragmentActivity, private val tabList: List<TabItem>) : FragmentStateAdapter(fragmentActivity) { override fun getItemCount() = tabList.size override fun createFragment(position: Int) = DateFilterFragment.newInstance( tabList[position].startTs, tabList[position].endTs ) }
3.3 按维度生成标签并绑定
// 示例:生成最近7天按日筛选的标签,按月/年筛选仅需调整时间计算规则即可 fun generateDayTabs(): List<TabItem> { val tabList = mutableListOf<TabItem>() val calendar = Calendar.getInstance() val dateFormat = SimpleDateFormat("MM/dd", Locale.getDefault()) // 倒序生成7天数据 for (i in 0 until 7) { calendar.set(Calendar.HOUR_OF_DAY, 0) calendar.set(Calendar.MINUTE, 0) calendar.set(Calendar.SECOND, 0) val startTs = calendar.timeInMillis val title = dateFormat.format(calendar.time) calendar.add(Calendar.DAY_OF_MONTH, 1) val endTs = calendar.timeInMillis tabList.add(TabItem(title, startTs, endTs)) // 跳转到前一天 calendar.add(Calendar.DAY_OF_MONTH, -2) } return tabList.reversed() } // Activity中绑定ViewPager和TabLayout val tabList = generateDayTabs() // 切换维度时替换为对应生成方法即可 binding.viewPager.adapter = FilterPagerAdapter(this, tabList) TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position -> tab.text = tabList[position].title }.attach()
4. Room查询适配
在DAO层添加范围查询方法,支持不同维度筛选:
@Dao interface BusinessDataDao { @Query("SELECT * FROM business_data WHERE dateTimestamp BETWEEN :startTs AND :endTs ORDER BY dateTimestamp DESC") suspend fun getDataByTimeRange(startTs: Long, endTs: Long): List<BusinessData> }
ViewModel层封装查询逻辑:
class BusinessViewModel(private val dao: BusinessDataDao) : ViewModel() { fun getDataByTimeRange(startTs: Long, endTs: Long) = liveData { emit(dao.getDataByTimeRange(startTs, endTs)) } }
注意事项
- 切换日/月/年筛选维度时,仅需重新生成对应规则的TabList,重新给ViewPager设置Adapter即可
- 时间计算注意时区适配,避免出现日期偏移问题
- 数据量较大时可给
dateTimestamp字段添加索引,提升查询效率 - 若使用旧版ViewPager,将Adapter替换为
FragmentPagerAdapter/FragmentStatePagerAdapter即可,逻辑完全一致
内容的提问来源于stack exchange,提问作者Jayod Kavinda
相关产品推荐
相关产品推荐

