如何在RemoteView中设置并更新RecyclerView?通知内数据配置疑问
Ah, I get it—you're trying to populate a RecyclerView inside a custom notification using RemoteViews, and you've hit the wall because you can't just call findViewById like you would in a regular Activity/Fragment. That's totally expected, because RemoteViews work differently—they're executed in the system's notification process, not your app's process, so direct view manipulation isn't allowed.
But don't worry, Android has an official way to handle this with RemoteViewsService and RemoteViewsFactory. Let me walk you through exactly how to set this up.
Step 1: Create a RemoteViewsFactory
This class acts as the "adapter" for your remote RecyclerView—it handles creating individual list items and providing data to them.
class NotificationListFactory( private val context: Context, private val dataList: List<String> ) : RemoteViewsService.RemoteViewsFactory { override fun onCreate() { // Initialize any resources here (e.g., load data from a database) } override fun getLoadingView(): RemoteViews? { // Optional: Return a view to show while loading data return null } override fun getItemId(position: Int): Long = position.toLong() override fun onDataSetChanged() { // Called when your data needs to be refreshed—use this to update your dataset } override fun hasStableIds(): Boolean = true override fun getViewAt(position: Int): RemoteViews { // Create the RemoteViews for a single list item val itemView = RemoteViews(context.packageName, R.layout.notification_list_item) // Populate the item with data (replace with your own views/data) itemView.setTextViewText(R.id.item_text, dataList[position]) // Optional: Add a click listener to the item val clickIntent = Intent(context, YourTargetActivity::class.java) val pendingIntent = PendingIntent.getActivity( context, position, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) itemView.setOnClickPendingIntent(R.id.item_container, pendingIntent) return itemView } override fun getCount(): Int = dataList.size override fun getViewTypeCount(): Int = 1 // Return the number of different item types override fun onDestroy() { // Clean up any resources here } }
Step 2: Create a RemoteViewsService
This service connects your notification's RecyclerView to the factory you just created. The system will bind to this service to get the factory instance.
class NotificationListService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { // Retrieve data passed from the notification creation code val dataList = intent.getStringArrayListExtra("DATA_LIST") ?: emptyList() return NotificationListFactory(this@NotificationListService, dataList) } }
Step 3: Register the Service in Manifest
The system needs permission to bind to this service, so add this to your AndroidManifest.xml:
<service android:name=".NotificationListService" android:permission="android.permission.BIND_REMOTEVIEWS" />
Step 4: Update Your Notification Creation Code
Now, modify your existing code to link the RecyclerView in your custom layout to the service and factory.
// 1. Prepare your dataset val notificationData = listOf("First Item", "Second Item", "Third Item") // 2. Create your main notification RemoteViews val contentView = RemoteViews(packageName, R.layout.notification_layout) // 3. Link the RecyclerView to your RemoteViewsService val adapterIntent = Intent(this, NotificationListService::class.java) adapterIntent.putStringArrayListExtra("DATA_LIST", ArrayList(notificationData)) // Replace R.id.notification_recycler_view with the ID of RecyclerView in your notification layout contentView.setRemoteAdapter(R.id.notification_recycler_view, adapterIntent) // 4. Optional: Set an empty view to show when the list is empty contentView.setEmptyView(R.id.notification_recycler_view, R.id.empty_view) // 5. Build and show the notification val channelId = "YOUR_NOTIFICATION_CHANNEL_ID" // Make sure this channel is created for Android O+ val mBuilder = NotificationCompat.Builder(this, channelId) .setSmallIcon(R.mipmap.ic_launcher) .setContent(contentView) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) // Ensures proper styling for custom views val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(123, mBuilder.build()) // Use a unique notification ID
Key Notes for Updating the RecyclerView
- To update the list data, simply re-build the notification with the new dataset and call
notificationManager.notify(NOTIFICATION_ID, updatedNotification)—the system will automatically triggeronDataSetChanged()in your factory to refresh the views. - Make sure your notification channel is properly created (required for Android 8.0 and above).
- The RecyclerView in your notification layout works as an "AdapterView" under the hood, so you can use either
RecyclerVieworListViewin your layout—RecyclerViewis preferred for better performance.
内容的提问来源于stack exchange,提问作者Pedro Massango

