Skip to content

Instantly share code, notes, and snippets.

@LouisShark
Created August 4, 2018 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LouisShark/d7bad7e8ace032469f198fb5a0bc09c9 to your computer and use it in GitHub Desktop.
Save LouisShark/d7bad7e8ace032469f198fb5a0bc09c9 to your computer and use it in GitHub Desktop.
Service Locator's imple
package com.yibo.housekeeping.test
import android.annotation.SuppressLint
import android.content.Context
import android.support.annotation.NonNull
import android.support.annotation.Nullable
/**
* @author LouisShark
* @date 2018/8/4.
* this is on com.yibo.housekeeping.test.
*/
class Sl private constructor() {
interface IService
interface Creator<out T> {
fun newInstance(@NonNull context: Context): T
}
companion object {
private val sServicesInstances = HashMap<String, Any>()
private val sServicesImplementationsMapping = HashMap<String, Class<*>>()
@SuppressLint("StaticFieldLeak")
private lateinit var mContext: Context
private val sServicesInstancesLock = Any()
fun init(@NonNull context: Context) {
mContext = context.applicationContext
}
/**
* Return instance of desired class or object that implement desired interface.
*/
@Suppress("UNCHECKED_CAST")
fun <T> get(@NonNull clazz: Class<T>): T {
val instance = getService(clazz.name, mContext)
return instance as T
}
/**
* This method allows to bind a custom service implementation to an interface.
*
* @param interfaceClass interface
* @param implementationClass class which implement interface specified in first param
*/
fun bindCustomServiceImplementation(
interfaceClass: Class<*>,
implementationClass: Class<*>
) {
synchronized(sServicesInstancesLock) {
sServicesImplementationsMapping.put(interfaceClass.name, implementationClass)
}
}
@NonNull
private fun getService(@NonNull name: String, @Nullable applicationContext: Context): Any {
synchronized(sServicesInstancesLock) {
return sServicesInstances[name] ?: try {
val clazz: Class<*> =
if (sServicesImplementationsMapping.containsKey(name)) {
sServicesImplementationsMapping[name]!!
} else {
Class.forName(name)
}
val serviceInstance = try {
clazz.getDeclaredConstructor(Context::class.java)
.newInstance(applicationContext)
} catch (e: NoSuchMethodException) {
clazz.getDeclaredConstructor().newInstance()
} as? Sl.IService
?: throw IllegalArgumentException("Required service must implement IService interface")
sServicesInstances[name] = serviceInstance
return serviceInstance
} catch (e: ClassNotFoundException) {
throw IllegalArgumentException(
"Requested service class was not found: $name",
e
)
} catch (e: Exception) {
throw IllegalArgumentException(
"Cannot initialize requested service: $name",
e
)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment