Overriding ViewModelStore - java

Is it possible to provide once own implementation of a ViewModelStore for ViewModelProviders to use instead of the default one?
More precisely, I'm interested in adding fun clear(vm: ViewModel) (or using an index or something similar) functionality to the ViewModelStore so that I can clear a single view model of my choice, not just use the built in ViewModelStore#clear:
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
which clears all view models.

First, I think you should not consider doing that, because that's an implementation detail of Architecture Components library. Most possibly you should come up with a better solution as a result of adapting your use-case to match guidelines/contracts exposed by ViewModels API.
Nevertheless, let's examine possibilities of doing that.
Here's the code, that we should use in order to obtain a ViewModel implementation:
val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
What will this code result in, is that it will create an instance of HolderFragment, which is a retained fragment, and will attach it to this's fragment manager (might be either FragmentActivity's fragment manager or Fragment's child fragment manager).
This HolderFragment will be added with a HolderFragment.HOLDER_TAG, thus we are able to get an instance of this fragment from the fragment manager.
val holderFragment = supportFragmentManager.findFragmentByTag("android.arch.lifecycle.state.StateProviderHolderFragment") as HolderFragment
It's the HolderFragment, that creates an instance of ViewModelStore and keeps that instance as a private field. There exists a getter for that field, but there does not exist a setter, which means, that the only way to "substitute" this object is by using reflection.
But before doing that, let's try to write a custom implementation of ViewModelStore class:
class MyViewModelStore : ViewModelStore() {
private val mMap = HashMap<String, ViewModel>()
internal fun put(key: String, viewModel: ViewModel) {
val oldViewModel = mMap.put(key, viewModel)
oldViewModel?.onCleared() // COMPILATION ERROR -> Cannot access 'onCleared': it is protected/*protected and package*/ in 'ViewModel'
}
internal operator fun get(key: String): ViewModel? {
return mMap[key]
}
override fun clear() {
for (vm in mMap.values) {
vm.onCleared() // COMPILATION ERROR -> Cannot access 'onCleared': it is protected/*protected and package*/ in 'ViewModel'
}
mMap.clear()
}
}
Unfortunately, we cannot do that, because ViewModel#onCleared() has a protected package access, which makes impossible for us call it outside of the android.arch.lifecycle package. Again, we can use reflection to do that (but how good is that?).
Despite being not advised (by me), seems like that's also not achievable to do (without using reflection).

Related

LiveDataBuilder for one off events

In the Android docs i found this article about conditional navigation where a login function returns LiveData to propagate the signIn result back from the viewmodel to the fragment. I assume the viewModel uses LiveDataBuilder to create the LiveData
//Fragment
fun login(username: String, password: String) {
userViewModel.login(username, password).observe(viewLifecycleOwner, Observer { result ->
if (result.success) {
savedStateHandle.set(LOGIN_SUCCESSFUL, true)
findNavController().popBackStack()
} else {
showErrorMessage()
}
})
}
I assume viewmodel does something like this.
fun login(username: String, password: String) = liveData {
//perform login
}
I always thought this is bad practice since it creates a Livedata object on every login attempt. In this case i mostly use another SingleLiveData object to post the login result to. I also used callbacks quite often. Something like this:
fun login(username: String, password: String) {
userViewModel.login(username, password,
onSuccess = {
//DO SOMETHING
}, onError = {
//DO SOMETHING
})
}
Can someone explain which is now the best approach and what is the reason the other appraoches should not be used?
You must not use callbacks in that way. You are leaking the views to the ViewModel.
LiveData used in this way is basically a glorified callback that will automatically be cancelled when the Fragment's view goes out of scope, so it's easier to use safely on the Fragment, and it avoids leaking the Fragment to the ViewModel. It saves you a lot of boilerplate that would be required to do it safely and without leaking the Fragmet.
I always thought this is bad practice since it creates a Livedata object on every login attempt.
I don't see what's bad about that. It's a lightweight object. Probably lighter weight than most of the Strings you work with in an app.

How to Override a suspend function in java class

Consider the following interface in kotlin:
LoginRepository.kt
interface LoginRepository {
suspend fun login(): LoginResponse
}
LoginRepo.java
class LoginRepo implements LoginRepository {
public Object login(#NonNull Continuation<? super LoginResponse> $completion) {
api.login((result) -> {
ContinuationUtilsKt.resumeContinuationWithSuccess($completion, result);
});
return null;
}
}
ContinuationUtils.kt
fun <T> resumeContinuationWithSuccess(cont: Continuation<T>, value: T) {
cont.resumeWith(Result.success(value))
}
I've attempted to drill down the code to its essential parts, i.e. a suspend function that is overridden in the java class makes an API call and returns a success or failure continuation using the continuation object and returns null.
However, the method LoginRepository.login when called returns null.
The overridden method signature in LoginRepo is generated by the IDE.
Am I supposed to return some object instead of null? Or something else that I'm missing.
I really don't think you're supposed to do this. The functions and classes used to implement it in Kotlin are internal/private and hidden from the Java side.
Basically, you need to intercept the original Continuation and resume the new returned Continuation with your return value. Then return Intrinsics.COROUTINE_SUSPENDED to indicate that you are not synchronously returning a value. If the return value is anything besides Intrinsics.COROUTINE_SUSPENDED, then I think it assumes you are directly returning the declared return value of the suspend function.
While this code may work, it probably doesn't handle all the edge cases, and it probably won't provide helpful stack traces in the event of a crash. The standard library implementation is far more complicated.
class LoginRepo implements LoginRepository {
public Object login(#NonNull Continuation<? super LoginResponse> $completion) {
Continuation<? super LoginResponse> cont = IntrinsicsKt.intercepted($completion);
api.login((result) -> {
ContinuationUtilsKt.resumeContinuationWithSuccess(cont, result);
});
return IntrinsicsKt.getCOROUTINE_SUSPENDED();
}
}
Kotlin interoperability with Java doesn't really include suspend functions. Suspend functions are very specific to Kotlin, they are hard to both invoke and to implement from Java.
In most cases I suggest to not even try to handle continuations and suspendable code from Java and instead create small "adapters" in Kotlin. These adapters would translate suspendable code to something more usable from Java. For example, in Kotlin it is pretty easy to convert between suspend functions and CompletableFuture - in both directions.
Your case is more tricky, because you need to implement an interface. Still, there are ways to handle this from Kotlin. We can for example create abstract implementation of LoginRepository in Kotlin. It would provide login(), but you would implement all remaining methods in Java. We can do a similar thing using composition instead of inheritance by creating a non-abstract implementation of LoginRepository in Kotlin (throwing errors from all unrelated functions) and delegating to it from the Java class. Or we can create a static function that performs the conversion from callback-based API to suspend API. This solution is the most flexible, but we need to mess with some coroutines internals from Java:
#file:JvmName("SuspendUtils")
// utility function in Kotlin, it converts callback API to a suspend function
suspend fun login(api: Api): LoginResponse = suspendCoroutine { cont ->
api.login { cont.resume(it) }
}
public static class LoginRepo implements LoginRepository {
private Api api = new Api();
#Nullable
#Override
public Object login(#NotNull Continuation<? super String> $completion) {
return SuspendUtils.login(api, $completion);
}
}

how do i remove uri path information?

I have requirement like i need to deleted selected file information if anybody selected wrong file, but after call delete() method its deleted from gallery also,
my question is how can remove selected file URI information i dont want to delete selected file form gallery, any help?
Working with Android Architecture Components, such as: View Model, LiveData, etc. I would like to suggest you to follow Official Guide from Android.
When using Android Architecture Components to call a API request, how I try to achieve my goal is as follow:
Create one Repo class, in that class, initialize the Retrofit Interface(if using Retrofit). Create a function that calls the required API, handle request response and returns a Live Data. Make extra functions for the parameter to be passed with URL.
Create one View Model class, in that class, initialize above Repo class. Create a function that calls repo class function which returns Live Data and this function also returns LiveData. Make extra functions for the parameter to be passed to Repo for adding with URL.
In your View class (Activity/Fragment), initialize View Model class and pass those parameters which are required URL params. Call the View Model function, which returns Live Data and observe that in your View class.
You will get data in your View Class when any change appears in Live Data.
Above is a simple practice, but it can be made good by making responses generic according to your requirement.
You can create public function in VM and pass desired paramas to it and then invoke desired URL from repo .
Refer example
https://github.com/googlesamples/android-architecture-components/blob/master/BasicSample/app/src/main/java/com/example/android/persistence/viewmodel/ProductListViewModel.java
you can call some public method from viewmodel and then pass params to it.somehow like this
viewmodel
class UserViewmodel: ViewModel() {
fun callApi(userId: String) : Any {
// Your method definition
return result
}
}
and in activity / fragment call method via viewmodel instance
class UserActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
val viewModel = ViewModelProviders.of(this).get(UserViewmodel::class.java)
val result = viewModel.callApi("userId")
}
}

Change persistence layer dynamically (upon runtime) with as few changes as possible

I am searching for a design pattern/way to exchange a (persistence) layer of my application dynamically (preferably even at runtime).
Why?
I'd like to be able to decide whether to save certain data to XML or a database on a "per instance"-basis. So I may decide that one project uses XML as a backend and another uses a database. I want to be flexible here and to be able to easily add another "driver" for e.g. Json or whatever.
Now assume the following setup:
We have a controller and we want to manage some data. We can choose between a SQL and XML implementation.
One possible (working) solution:
BasicController.scala
val myPersistenceLayer: PersistenceLayer = SQLPersistenceLayer
val apples: Seq[Apple] = myPersistenceLayer.getApples()
trait PersistenceLayer
{
def getApples(): Seq[Apple]
def getBananas(): Seq[Banana]
}
object SQLPersistenceLayer extends PersistenceLayer
{
override def getApples(): Seq[Apple] = {...}
override def getBananas(): Seq[Banana] = {...}
}
This is a rather nasty solution as one would have to add methods for each new Model (think fruit! ;)) not only in the trait, but also in every implementation. I like my single responsibility so I'd rather delegate that to the models instead, like:
trait PersistenceLayer
{
def getAll(model: Model): Seq[Model] = { model.getAll() }
}
trait Model
{
def getAll(): Seq[Model]
}
package "SQL"
class Apple extends Model
{
def getAll(): Seq[Apple] = { // do some SQL magic here }
}
package "XML"
class Apple extends Model
{
def getAll(): Seq[Apple] = { // do some XML magic here instead }
}
Now the big problem here is, even if I implement a concrete PersistenceLayer, like so:
object SQLPersistenceLayer extends PersistenceLayer {}
how could I tell the application to use the model of the right package?
If I use the SQLPersistenceLayer upon:
val apples = myPersistenceLayer.get(Apple)
I would need to import the right "Apple" class, which defeats the whole purpose because then I could just remove all other classes, import the right one and just use a generic "getAll()" method on it.
So again I would need to change the implementation at multiple lines, which is what I want to avoid.
I thought about something like giving a string with the package-name, like
val package = "sql" and in the controller to import it from the right package, but this is not really feasible and not really easy to accomplish and it's a rather nasty hack for something I'm obviously missing.
To make a long story short: I want to be able to switch the package to use for my persistence needs dynamically. In some dynamically typed languages I could come up with a solution, but not in Scala or any statically typed language, so I guess I'm not knowing a certain design pattern here
** Edit **
A thought occurred (ya, sometimes it happens ;)) and now I'm wondering whether something like this could lead to what I want:
namespace tld.app.persistence
trait PersistenceLayer
{
proteced val models: mutable.HashMap[String, Model] = new mutable.HashMap[String, Model]
def registerModel(key: String, model: Model): Unit =
{
models.remove(key)
models.put(key, model)
}
def get(model: String): Seq[Future[Model]] =
{
val m: Model = models.getOrElse(model, throw new Exception("No such model found!"))
m.get
}
}
trait Model
{
def get(): Seq[Future[Model]]
}
namespace tld.app.persistence.sql
object SQLPersistenceLayer extends PersistenceLayer
class Person extends Model
{
def get(): Seq[Future[Model]] =
{
// ... query the database
}
}
namespace tld.app.persistence.xml
object XMLPersistenceLayer extends PersistenceLayer
class Person extends Model
{
def get(): Seq[Future[Model]] =
{
// ... read in from the appropriate xml-file
}
}
object Settings
{
var persistenceLayer: PersistenceLayer = SQLPersistenceLayer // Default is SQLPersistenceLayer
}
Somewhere in the application:
Settings.persistenceLayer.get("person")
// Then a user-interaction happens
Settings.persistenceLayer = XMLPersistenceLayer
Settings.persistenceLayer.get("person")
The persistenceLayer normally stays the same, but the user can decide upon changing it. I'll have a deeper look at it, as soon as I can find time. But maybe somebody immediately spots a problem with that approach.
DI allows you to wire an implementation at compile time. There are many ways to do DI in Scala (Cake Pattern, Reader Monad, DI frameworks, etc).
If you want to wire the dependency on application startup then regular dependency mechanisms would work. You would just create an instance of desired dependency (SQL, XML) based on some condition and pass it to the code.
If you want to keep switching between dependencies during your application execution, i.e. sometimes you save to SQL, other times to XML then you can use something similar to Lift Injector, see also my answer here - option 2.
You can use runtime reflection to accomplish it. You need to specify and create class/object at runtime which you'll be passing to Persistency layer and then just call generic getAll method.
For details of reflection library -> http://docs.scala-lang.org/overviews/reflection/overview.html
It would be better to make companion object Apple which has getAll method implemented differently for each persistency layer.
Then access Apple objects with reflection by using full package name
val apple:sql.Apple = //Reflection library object access
val apple:xml.Apple = //Reflection library object access
val apples = myPersistenceLayer.get(apple)
I think you can achieve module-based inclusion with implicits + TypeTags with something along these lines
object SqlPersistence {
implicit def getAll[T: TypeTag](): Seq[T] = {/* type-based sql implementation*/}
}
object JsonPersistence {
implicit def getAll[T: TypeTag](): Seq[T] = {/* type-based json implementation*/}
}
object PersistenceLayer {
def getAll[T](implicit getter: Unit => Seq[T]): Seq[T] = getter
}
// somewhere else ...
import SqlPersistence._
PersistenceLayer.getAll[Apple]
The advantage is that you can decide on your persistence layer at the spot by bringing a corresponding import. The major downside is the same: you need to decide on your persistence layer with every call and make sure that it is what you think. Also, from my personal experience compiler is less helpful with tricky implicit corner cases, so there is a potential to spend more time debugging.
If you set your persistence layer once for an app, then DI would do fine, e.g. cake pattern. But then again, you either need to have a method per class or resort to reflection. Without reflection, it may look like that:
trait PersistenceLayer {
def getApples(): Apples
}
trait SqlPersistenceLayer extends PersistenceLayer {
override def getApples() = // sql to get apples
}
trait Controller {
this: PersistenceLayer =>
def doMyAppleStuff = getApples()
}
// somewhere in the main ...
val controller = new Controller with SqlPersistence {}
controller.doMyAppleStuff
Something similar is strategy pattern if that helps.
I think the repository pattern is your solution.
EDIT:
ok. thanks for "-1" thats ok because i did not explained my idea behind...
my example is only one of many others. so i hope that this is usefull for someone out there
i will try to explain my idea about using the repository and factory pattern.
for this i made a github repository with the example code: https://github.com/StefanHeimberg/stackoverflow-32319416
my setup ist nearly the same as in your question. but the difference is the following:
i did not use scala. but the concept would be the same...
my settings contains only a "flag" for the repository factory.
the "model" objects are persistence ignorance. that means the do not know how the are persisted. this is the concern of the repositories
i made dependency injection by hand cause this should be sufficient for the example
i have no "Controller" but i have "Application Services"...
the decition about the implementation used is made inside the factory on each call to the create() method.
the domain layer does not know anything about the used infrastructure implementation. the application layer is orchestrating the domain service and the infrastructure services (in my example only the repositories)
if you have any DI Container then the factory could by a Producer or soething else... depends on DI Container
package structure:
i have also made a simple integration test
public class AppleServiceIT {
private Settings settings;
private AppleService appleService;
#Before
public void injectDependencies() {
settings = new Settings();
final JdbcAppleRepository jdbcAppleRepository = new JdbcAppleRepository();
final JsonAppleRepository jsonAppleRepository = new JsonAppleRepository();
final AppleRepositoryFactory appleRepositoryFactory = new AppleRepositoryFactory(jdbcAppleRepository, jsonAppleRepository);
appleService = new AppleService(settings, appleRepositoryFactory);
}
#Test
public void test_findAppleById() {
// test with jdbc
settings.setRepositoryType(RepositoryTypeEnum.JDBC);
assertEquals("JDBC-135", appleService.findAppleById(135l).getMessage());
// test with json
settings.setRepositoryType(RepositoryTypeEnum.JSON);
assertEquals("JSON-243", appleService.findAppleById(243l).getMessage());
}
#Test
public void test_getApples() {
// test with jdbc
settings.setRepositoryType(RepositoryTypeEnum.JDBC);
assertEquals(2, appleService.getApples().size());
// test with json
settings.setRepositoryType(RepositoryTypeEnum.JSON);
assertEquals(3, appleService.getApples().size());
}
}

Using "Adapter" pattern

How I understand, the Goal of the Adapter pattern is to call some class methods using some interface (which opened to clients). To make adapter pattern we need to implement some interface (which uses by client), and also we need to extend some class, which methods client need to call when calling interface methods.
class Adapter extends NeedClass implements PublicInterface{}
But what if we haven't interface, but have only 2 classes? For example we have some class(not interface!) which methods uses clients. Now we need to call methods of other class by making adapter class, but we cant to do this, because we cant make multiple Inheritance on the adapter class.
class Adapter extends NeedClass, PublicInterface
above code doesnt work.
What we can do in this case?
You can has an instance of NeedClass in Adapter and call it, when you need. So you extend only from PublicInterface.
public class Adapter extends PublicInterface {
private NeedClass needClass;
#Override
public void doSomething() {
needClass.doSomethingElse("someParameter");
}
}
You can use a composition instead of inheritance. Add a field to Adapter class of type NeedClass:
public class Adapter extends PublicInterface {
private NeedClass needClass;
}
Then inside Adapter methods delegate execution to needClass field.
From what i have understood the Adapter Pattern.
it is helpful when dealing with the third part codes such as API which is/ are subject to changes any time and my likely to break your code if implemented direct.
For example : Using Paypal in your site for payment online.let's assume the Paypal uses the method payMoney() for payment. and after sometime they decide to change the method to something else let's say sendMoney(). This is likely to break your code if implemented directly, with the use of Adapter Design pattern this can be solves as follow
the third part code => Paypal
class Paypal {
public function __construct(){
// their codes
}
public function payMoney($amount){
// the logic of validating
// the $amount variables and do the payment
}
}
so implement it directly in the code as below will break the code
$pay = new Paypal();
$pay->payMoney(200);
using adapter will save numbers of hours and a complex work of updating the code from payMoney() to sendMoney() in every where that the API scripts has been implemented. Adapter enable update in one place and that's it.
Let see it.
class paypalAdapter {
private $paypal;
// Paypal object into construct and check if it's pa
// Paypal object via type hint
public function __construct(PayPal $paypal) {
$this->paypal = $paypal;
}
// call the Paypal method in your own
//custom method that is to be
// implemented directly into your code
public function pay($amount) {
$this->paypal->payMoney($amount);
}
}
so it is like that and there you can go and use the PaypalAdater directly into the code as follow;
$pay = new PaypalAdapter(new Paypal);
$pay->pay(200);
So in future when the Vendor(Paypal) decide to use sendMoney instead of payMoney what to be done is to open the PaypalAdapter class and do the following in the pay($amount) method:
// SEE THIS METHOD ABOVE TO OBSERVE CHANGES
// FROM $this->paypal->payMoney($amount);
// TO $this->paypal->senMoney($amount);
public function pay($amount) {
$this->paypal->sendMoney($amount);
}
After this minor change in one place, everything works well as before.

Categories