'Where should I call API in collection (configurable) android App widget
I have a configurable/reconfigurable collection Widget in this I have to call an API for a list so where can I call API (I need to change API when configuration change). I am trying to call post-API in the onCreate of Factory class.
I have 2 post-APIs, Both APIs return the same type of class so used the same list and same design file for load data when I change the configuration option from configuration activity I want to call the selected API again. but it didn't work
@AndroidEntryPoint
class MyWidgetServices : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return ListViewFactory(this.applicationContext, intent)
}
@Inject
lateinit var repo: WidgetRepo
@Inject
lateinit var prefs: PrefUtil
inner class ListViewFactory(context: Context, intent: Intent) :
RemoteViewsFactory {
private val mContext: Context = context
private val mAppWidgetId: Int = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID
)
private var list: MutableList<PendingResModel> = mutableListOf()
private var count: Long = 0
val appWidgetManager = AppWidgetManager.getInstance(mContext)
override
fun onCreate() {
// Since we reload the cursor in onDataSetChanged() which gets called immediately after
// onCreate(), we do nothing here.
this.hashCode().toString().logE()
if (prefs.showInProgress) {
CoroutineScope(Dispatchers.IO).launch {
repo.inProgress()?.let {
it.data?.let {
list.addAll(it)
appWidgetManager.notifyAppWidgetViewDataChanged(
mAppWidgetId,
R.id.lv_order
)
}
it.meta?.let { meta ->
count = meta.totalDataCount ?: 0
}
}
}
} else {
CoroutineScope(Dispatchers.IO).launch {
repo.toConfirm()?.let {
it.data?.let {
list.addAll(it)
appWidgetManager.notifyAppWidgetViewDataChanged(
mAppWidgetId,
R.id.lv_order
)
}
it.meta?.let { meta ->
count = meta.totalDataCount ?: 0
}
}
}
}
}
override fun onDestroy() {
list.clear()
}
override fun getCount(): Int {
return list.size
}
@SuppressLint("RemoteViewLayout")
override fun getViewAt(position: Int): RemoteViews {
val rv = RemoteViews(mContext.packageName, Layouts.row_widget)
val views = RemoteViews(mContext.packageName, R.layout.layout_widget)
views.setTextViewText(R.id.tv_count, count.toString())
Glide.with(mContext)
.asBitmap()
.load(list[position].user.profile)
.apply(RequestOptions.circleCropTransform())
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
rv.setImageViewBitmap(R.id.iv_widget_profile, resource)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
}
override fun onLoadCleared(placeHolder: Drawable?) {
}
})
rv.setTextViewText(R.id.tv_id, list[position].id)
rv.setTextViewText(R.id.tv_name, list[position].user.name)
return rv
}
override fun getLoadingView(): RemoteViews? {
// We aren't going to return a default loading view in this sample
return null
}
override fun getViewTypeCount(): Int {
// Technically, we have two types of views (the dark and light background views)
return 1
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun hasStableIds(): Boolean {
return true
}
override fun onDataSetChanged() {
}
}
}
this is the updateAppWidget function that is called in onUpdate of a widgetprovider class
internal fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
text: String = "In progress"
) {
val serviceIntent = Intent(context, MyWidgetServices::class.java)
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
serviceIntent.data = Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))
val views = RemoteViews(context.packageName, R.layout.layout_widget)
views.setTextViewText(R.id.tv_title, text)
views.setRemoteAdapter(appWidgetId, R.id.lv_widget, serviceIntent)
views.setEmptyView(R.id.lv_widget, R.id.empty_view)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
and here is the code of change configuration from the configuration activity
override fun onClick(v: View) {
super.onClick(v)
when (v) {
binding.tvProgress -> {
prefs.showInProgress = true
updateAppWidget(
this@ConfigureActivity,
appWidgetManager,
appWidgetId,
text = "In Progress"
)
// Make sure we pass back the original appWidgetId
val resultValue = Intent()
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId)
setResult(RESULT_OK, resultValue)
finish()
}
binding.tvConfirm -> {
prefs.showInProgress = false
updateAppWidget(this@ConfigureActivity,
appWidgetManager, appWidgetId, text = "To Confirm")
val resultValue = Intent()
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
setResult(RESULT_OK, resultValue)
finish()
}
}}
Solution 1:[1]
I found a solution I called APIs in onDataSetChanged instead of onCreate and take a global boolean variable to manage the recall APIs
override fun onDataSetChanged() {
if (AppConstants.Misc.isRefreshWidget) {
list.clear()
if (prefs.showInProgress) {
CoroutineScope(Dispatchers.IO).launch {
repo.inProgress()?.let {
it.data?.let {
list.addAll(it)
appWidgetManager.notifyAppWidgetViewDataChanged(
mAppWidgetId,
R.id.lv_order
)
}
it.meta?.let { meta ->
count = meta.totalDataCount ?: 0
}
AppConstants.Misc.isRefreshWidget = false
}
}
} else {
CoroutineScope(Dispatchers.IO).launch {
repo.toConfirm()?.let {
it.data?.let {
list.addAll(it)
appWidgetManager.notifyAppWidgetViewDataChanged(
mAppWidgetId,
R.id.lv_order
)
}
it.meta?.let { meta ->
count = meta.totalDataCount ?: 0
}
AppConstants.Misc.isRefreshWidget = false
}
}
}
}
}
and change this global variable (isRefreshWidget) on the click of configuring activity's button or whenever you want to call api
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | chandresh sidpara |
