Reputation: 73
In my App Activity, I am fetching data from GitHub API and storing it locally using Realm Database. Now in my App Widget, I am fetching that data from database and displaying it.
The widget has a ListView. Now, whenever the widget loads up, some of the elements of the ListView gets displayed, but the rest are just stuck at "Loading".
My Code for AppWidgetProvider
class GidgetWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(
context,
appWidgetManager,
appWidgetId,
)
}
super.onUpdate(context, appWidgetManager, appWidgetIds)
}
override fun onEnabled(context: Context) {}
override fun onDisabled(context: Context) {}
override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {}
}
internal fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
) {
val views = RemoteViews(context.packageName, R.layout.gidget_widget)
val clickIntent = Intent(context, GidgetWidget::class.java)
val clickPendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, 0)
views.setPendingIntentTemplate(R.id.appwidgetListView, clickPendingIntent)
val serviceIntent = Intent(context, WidgetRepoRemoteService::class.java)
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
views.setRemoteAdapter(appWidgetId, R.id.appwidgetListView, serviceIntent)
appWidgetManager.updateAppWidget(appWidgetId, views)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.appwidgetListView)
}
My code for RemoteViewsService
class WidgetRepoRemoteService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
println("onGetViewFactory")
return WidgetRepoRemoteViewsFactory(applicationContext, intent!!)
}
}
My Code for RemoteViewsFactory
class WidgetRepoRemoteViewsFactory(
private val context: Context,
intent: Intent,
) :
RemoteViewsService.RemoteViewsFactory {
private var dataSource: MutableList<AddToWidget> = mutableListOf()
private var appWidgetId = 0
init {
appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID
)
}
override fun onCreate() {
//adding static data
val temp = AddToWidget()
temp.username = "asdoasd"
temp.name = "asdoaksd"
temp.avatarUrl = "https://avatars.githubusercontent.com/u/15610556?"
temp.message = "random message"
temp.date = "today"
temp.icon = R.drawable.ic_github_issue
dataSource.add(temp)
}
override fun onDataSetChanged() {
//fetching data from database
val realm: Realm = Realm.getDefaultInstance()
val result = realm.where(AddToWidget::class.java).findAll()
dataSource = result
}
override fun onDestroy() = dataSource.clear()
override fun getCount(): Int = if (dataSource.size <= 10) dataSource.size else 10
@RequiresApi(Build.VERSION_CODES.O)
override fun getViewAt(position: Int): RemoteViews {
val views = RemoteViews(context.packageName, R.layout.appwidget_recycler_item)
val currentItem = dataSource[position]
views.setTextViewText(R.id.appwidgetRecyclerViewItemUsername, currentItem.username)
views.setTextViewText(R.id.appwidgetRecyclerViewItemRepoName, currentItem.name)
views.setTextViewText(R.id.appwidgetRecyclerViewItemMessage, currentItem.message)
views.setTextViewText(R.id.appwidgetRecyclerViewItemDate, currentItem.date)
val profilePhotoBitmap: Bitmap = Picasso.get().load(currentItem.avatarUrl).get()
views.setImageViewBitmap(R.id.appwidgetRecyclerViewItemProfilePhoto, profilePhotoBitmap)
views.setImageViewResource(R.id.appwidgetEventTypeIcon, currentItem.icon!!)
val fillIntent = Intent()
views.setOnClickFillInIntent(R.id.appwidgetRecyclerViewItemUsername, fillIntent)
return views
}
override fun getLoadingView(): RemoteViews? {
return null
}
override fun getViewTypeCount(): Int = 1
override fun getItemId(position: Int): Long = position.toLong()
override fun hasStableIds(): Boolean = true
}
Any help would be much appreciated!
Upvotes: 0
Views: 342
Reputation: 73
I solved the issue myself.
What I did is a workaround because apparently onDataSetChanged() of RemoteViewsFactory gets killed after a few seconds. So once the user chooses to add some data to the widget, I send it via broadcast to my AppWidgetProvider, and further to my RemoteViewsService and RemoteViewsFactory. But here's the catch, we have to send an ArrayList from AppWidgetProvider to RemoteViewsFactory only after wrapping my ArrayList in a bundle and sending that bundle via intent. I was mainly stuck at this point because I didn't realize I had to do that.
I hope this answer saves time of those who might be in similar situation as me.
Upvotes: 1