如何为集成Firebase Cloud Messaging的应用创建RecyclerView通知列表Activity?
嘿,我来帮你搞定这个需求!要实现用RecyclerView展示用户收到的所有FCM通知,核心是先把收到的通知存下来(毕竟FCM不会自动帮你保存历史通知),再用RecyclerView把存储的数据渲染出来。下面是一步步的具体操作,非常清晰:
第一步:先把FCM通知存储到本地
推荐用Room数据库来存储通知数据,它适合结构化数据的持久化,比SharedPreferences更适合多通知场景:
- 定义Notification实体类,用来映射数据库表
@Entity(tableName = "notifications") data class NotificationEntity( @PrimaryKey(autoGenerate = true) val id: Int = 0, val title: String, val content: String, val timestamp: Long // 记录通知收到的时间戳,方便排序 )
- 创建Dao接口,定义数据库操作方法
@Dao interface NotificationDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertNotification(notification: NotificationEntity) @Query("SELECT * FROM notifications ORDER BY timestamp DESC") fun getAllNotifications(): Flow<List<NotificationEntity>> // 用Flow实现数据变化监听 }
- 创建Room数据库单例类
@Database(entities = [NotificationEntity::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun notificationDao(): NotificationDao companion object { @Volatile private var INSTANCE: AppDatabase? = null fun getDatabase(context: Context): AppDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "app_database" ).build() INSTANCE = instance instance } } } }
- 在FCM消息服务中存储通知
不管前台还是后台收到FCM消息,都要在FirebaseMessagingService的onMessageReceived回调里把通知数据插入数据库:
class MyFirebaseMessagingService : FirebaseMessagingService() { private lateinit var notificationDao: NotificationDao override fun onCreate() { super.onCreate() val db = AppDatabase.getDatabase(this) notificationDao = db.notificationDao() } override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) // 提取通知内容,兼容没有标题/内容的情况 val title = remoteMessage.notification?.title ?: "无标题" val content = remoteMessage.notification?.body ?: "无内容" val timestamp = System.currentTimeMillis() // 用协程在IO线程插入数据库 CoroutineScope(Dispatchers.IO).launch { notificationDao.insertNotification( NotificationEntity(title = title, content = content, timestamp = timestamp) ) } // 保留你原来的通知推送逻辑 // ... } }
第二步:编写RecyclerView适配器
这个适配器负责把数据库里的通知数据渲染到列表项上:
class NotificationAdapter(private val notifications: List<NotificationEntity>) : RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder>() { inner class NotificationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvTitle: TextView = itemView.findViewById(R.id.tv_notification_title) val tvContent: TextView = itemView.findViewById(R.id.tv_notification_content) val tvTime: TextView = itemView.findViewById(R.id.tv_notification_time) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_notification, parent, false) return NotificationViewHolder(view) } override fun onBindViewHolder(holder: NotificationViewHolder, position: Int) { val notification = notifications[position] holder.tvTitle.text = notification.title holder.tvContent.text = notification.content // 把时间戳格式化成可读的日期时间 val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()) holder.tvTime.text = dateFormat.format(Date(notification.timestamp)) } override fun getItemCount() = notifications.size }
对应的列表项布局item_notification.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="wrap_content" android:orientation="vertical" android:padding="12dp" android:background="?android:attr/selectableItemBackground"> <TextView android:id="@+id/tv_notification_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" android:textStyle="bold"/> <TextView android:id="@+id/tv_notification_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" android:layout_marginTop="4dp"/> <TextView android:id="@+id/tv_notification_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" android:textColor="@android:color/darker_gray" android:layout_marginTop="8dp"/> </LinearLayout>
第三步:创建通知列表Activity
先写Activity的布局activity_notification_list.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"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_notifications" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp"/> </LinearLayout>
然后写Activity的逻辑代码,监听数据库数据变化,实时更新RecyclerView:
class NotificationListActivity : AppCompatActivity() { private lateinit var notificationDao: NotificationDao private lateinit var adapter: NotificationAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_notification_list) val db = AppDatabase.getDatabase(this) notificationDao = db.notificationDao() // 初始化RecyclerView val rvNotifications = findViewById<RecyclerView>(R.id.rv_notifications) rvNotifications.layoutManager = LinearLayoutManager(this) adapter = NotificationAdapter(emptyList()) rvNotifications.adapter = adapter // 用生命周期协程监听数据库数据变化,自动更新列表 lifecycleScope.launch { notificationDao.getAllNotifications().collect { notifications -> adapter = NotificationAdapter(notifications) rvNotifications.adapter = adapter } } } }
最后别忘在AndroidManifest.xml里注册这个Activity:
<activity android:name=".NotificationListActivity"/>
额外小提示
- 如果你用Java开发,只需要把Kotlin代码转成对应的Java语法就行,核心逻辑完全一致。
- 要是通知数量特别多,可以考虑添加分页加载,避免一次性加载大量数据拖慢性能。
- 还能给列表项加点击事件,比如点击跳转到对应内容的详情页面。
内容的提问来源于stack exchange,提问作者Shubham Kumar
相关产品推荐
相关产品推荐

