I have an interface GalleryImagesDataCallback
which I use to pass data from background thread to UI thread, to avoid calling runOnUiThread()
from each overriden method of GalleryImagesDataCallback
, I have used kotlin higher order function.
interface GalleryImagesDataCallback {
fun fetchedList(list: ArrayList<ImageGalleryItemModel>)
@JvmDefault
fun callMethodOnUIThreadForFetch(mContext: Context, list:ArrayList<ImageGalleryItemModel>,func: (ArrayList<ImageGalleryItemModel>) -> Unit) {
(mContext as BaseActivity).runOnUiThread {
Logger.error("TEST_ABC","callMethodOnUIThreadForFetch Enter")
func(list)
}
}
fun deleteList()
@JvmDefault
fun callMethodOnUIThreadForDelete(mContext: Context, func: () -> Unit) {
(mContext as BaseActivity).runOnUiThread {
Logger.error("TEST_ABC","callMethodOnUIThreadForDelete Enter")
func()
}
}
}
Calling from background thread:
callback.callMethodOnUIThreadForFetch(mContext,list) {list:ArrayList<ImageGalleryItemModel> -> callback.fetchedList(list)} // callback is reference of GalleryImagesDataCallback
callback.callMethodOnUIThreadForDelete(mContext) {callback.deleteList()}
Problem :
Right now I'm having 2 separate methods callMethodOnUIThreadForDelete()
and callMethodOnUIThreadForFetch()
. Is there any way in kotlin to create one generic method (say callMethodOnUIThread()
) which I can use to call deleteList()
and fetchedList()
both with no change in function definition?
First to answer your literal question, your callMethodOnUIThreadForFetch
function has unnecessary redirection of the list
argument. Why make the list an argument of the higher-order function only to pass it right back to the function argument? You could use your callMethodOnUIThreadForDelete
function for either purpose, but suppose we rename it and remove the unsafe cast to Activity by using a Handler:
// In interface:
fun callMethodOnUIThread(context: Context, func: () -> Unit) {
Handler(context.mainLooper).post(func)
}
// From background thread:
callback.callMethodOnUIThread(mContext) { callback.fetchedList(list) }
callback.callMethodOnUIThread(mContext) { callback.deleteList() }
Assuming that you want to simplify the work of implementing this interface, then I don't think this actually helps. You've pushed the work of calling code on the UI thread from the interface implementation into the user of the interface. You may as well create a global helper function, instead of cluttering your interface, which is a weird place for it. Usage becomes more straightforward:
// Global utility function, not in a class
fun Context.onUiThread(func: () -> Unit) {
Handler(mainLooper).post(func)
}
// Usage:
mContext.onUiThread { callback.fetchedList(list) }
mContext.onUiThread { callback.deleteList() }
If you really want to fully encapsulate the thread switching, you would have to change your interface into an abstract class like this:
abstract class GalleryImagesDataCallback {
protected abstract fun fetchedListImpl(list: List<String>)
protected abstract fun deleteListImpl()
fun fetchedList(context: Context, list: List<String>) {
Handler(context.mainLooper).post { fetchListImpl(list) }
}
fun deleteList(context: Context) {
Handler(context.mainLooper).post { deleteListImpl() }
}
}
So instead of implementing the interface, you would create subclasses of this and implement the two abstract functions. Neither the subclass or the user of the callback has to be concerned with ensuring code is called on the UI thread.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments