How to acces shared viewModel in my recyclerAdapter - android-studio

My viewModel contains some variables such as how many cardViews should be created in the recyclerView. Therefore, I am looking for a way to access the same viewModel object in my adapter class. Is there a way to do so or a better alternative? My code is in kotlin
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
private val gameViewModel: GameViewModel by activityViewModels()

Since you have provided only 2 lines of code it is hard to know exactly what you are doing wrong.
Normally you would retrieve a ViewModel in an Activity class or a Fragment class like this
class MyActivity /* other stuff */ {
// this line produces/retrieves an instance of GameViewModel
// where its owner is MyActivity
private val gameViewModel: GameViewModel by viewModels()
}
Then somewhere else inside your activity class, you instantiate your RecycleAdapter class. There you would pass the gameViewModel to it. Of course, to be able to do that your RecyclerAdapter would either have to accept a GameViewModel as a constructor parameter, or through a setter, or some other function call.
Here is an example through a constructor parameter. Your RecyclerAdapter class would have to be defined something like this (note that this is Kotlin concise syntax for declaring properties and initializing them from the primary constructor)
class RecyclerAdapter(
private val gameViewModel: GameViewModel,
// add more constructor parameters/class properties here if needed
) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
// other class properties that you don't want to initialize
// through the primary constructor
// ...
// the class body where you implement RecyclerView.Adapter<> methods
// ...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// gameViewModel can be used here
gameViewModel.doSomething()
}
}
And as a last step, modify the line in your code, where you create your RecyclerAdapter instance
// here we create a new RecyclerAdapter and pass the gameViewModel to it
val adapter = RecyclerAdapter(gameViewModel)
recyclerView.adapter = adapter

Your Fragment's views should have a shorter lifecycle than your associated ViewModel, so it should be OK to pass it in as a constructor parameter.
class RecyclerAdapter(private val gameViewModel: GameViewModel) :
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
//...
}
Then pass the view model reference in from the Fragment when you instantiate the adapter in onViewCreated().
Personally, I wouldn't do this because presumably your ViewModel has lots of stuff in it that is irrelevant to the Adapter. Separation of concerns. I would make parameters only for the properties that are needed and let the Fragment pass them along from the ViewModel.

Related

How do I create a custom FilterRule with an override for ElementPasses

I want to create my own Boolean operation on an element to pass in as a FilterRule. The ElementPasses member description states:
Derived classes override this method to implement the test that determines whether the given element passes this rule or not.
I have tried to create my own derived class but I can't figure out how to implement it. I would think an interface would be available but I can't find anything. Annoyingly, I remember seeing an example of this but I can't seem to find anything.
This fails with: Static class 'ParameterDefinitionExists' cannot derive from type 'FilterRule'. Static classes must derive from object.
static public class ParameterDefinitionExists : FilterRule
{
public static bool ElementPasses(Element element)
{
return true;
}
}
And this fails with:'FilterRule' does not contain a constructor that takes 0 arguments
static public class ParameterDefinitionExists : FilterRule
{
new public bool ElementPasses(Element element)
{
return true;
}
}
What constructor arguments does it take?
There may be another way to go about it but I can't anything for FilterRules. I'm trying to define and refine a trigger in an updater but maybe I should query the element after it is passed in to the command. I imagine catching it with a filter rule is more efficient.
You have to use one of the Revit API classes derived from FilterRule:
Inheritance Hierarchy
System Object
Autodesk.Revit.DB FilterRule
Autodesk.Revit.DB FilterCategoryRule
Autodesk.Revit.DB FilterInverseRule
Autodesk.Revit.DB FilterValueRule
Autodesk.Revit.DB SharedParameterApplicableRule
Cf. http://www.revitapidocs.com/2017/a8f202ca-3c88-ecc4-fa93-549b26a412d7.htm
The Building Coder provides several examples creating and using parameter filters:
http://thebuildingcoder.typepad.com/blog/2010/08/elementparameterfilter-with-a-shared-parameter.html
Here is the entire topic group on filtering.

How to restore metaclass on object to original class definition

I've been trying to create a TEMPORARY override on new objects, and then to remove the override on the objects themselves. I'm not sure if this can be done, but here is what I've tried so far.
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
// I have two integration points one of them is Here before construction:
// First integration point:
// Save actual validate function
def realValidate = Validator.&validate
// Make new instances of Validator have the validate function hardwired to true
Validator.metaClass.validate { -> println "hardwired true"; true }
// Code I'd rather not modify
// Now some code executes which news up an instance and calls validate
def validator = new Validator()
validator.validate() // This correctly calls our override
// Second integration point.
// Without newing up a new Validator object, I'd like to remove the override.
Validator.metaClass = null
validator.metaClass.validate = Validator.&validate
// This throws "java.lang.IllegalArgumentException: object is not an instance of declaring class"
//validator.validate()
// So maybe I have to explicitly say:
realValidate.resolveStrategy = Closure.DELEGATE_FIRST
// But this still throws the same exception
//validator.validate()
// Perhaps if I tell my objects metaclass to forget about validate, it will bubble up and look for the method on its declaring class?
validator.metaClass.validate = { -> throw new MissingMethodException("validate", Validator.class, (Object[])[], false) }
// This throws MissingMethodException: No signature of method: Validator.validate() is applicable for argument types: () values: []
// Possible solutions: validate(), wait()
//validator.validate()
Apologies for not having a super specific question, since I don't know what all is possible in this particular area. I'd love both the reason why my code doesn't work, as well as alternatives to make it work.
This could be a per instance meta class problem... Validator.metaClass = null will set the global meta class for the Validator class to default. but your validator instance here is a Groovy class and thus stores a separate reference to the meta class in the instance itself. Calls with that instance will not go through a lookup of the global meta class and instead use the per instance meta class (the reference stored in the instance itself). Thus validator.metaClass = null is the only way to reset this
A small modification to your strategy would be fruitful. Use metaClass on the object instead of the Class.
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
def validator = new Validator()
// mark that the pointer is on object instead of class
def realValidate = validator.&validate
validator.metaClass.validate { -> println "hardwired true"; true }
validator.validate() // This correctly calls our override
// Second integration point.
// DO NOT NEED THIS
// validator.metaClass = null
// Assign the method pointer to validate to call original validate
validator.metaClass.validate = realValidate
validator.validate()
Your approach did not work because you had validate() overridden on the metaClass of Class reference instead of the object itself.

groovy: variable scope in closures in the super class (MissingPropertyException)

I have the impression that closures run as the actual class being called (instead of the implementing super class) and thus break when some variables are not visible (e.g. private in the super class).
For example
package comp.ds.GenericTest2
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
this.add(obj)
}
}
b = new ClosureScopeD()
// THIS THROWS groovy.lang.MissingPropertyException: No such property: accessThisPrivateVariable for class: comp.ds.GenericTest2.ClosureScopeD
b.doSomething("abc")
The last line throws a MissingPropertyException: the child class calls the "add" method of the super class, which executes the "each" closure, which uses the "accessThisPrivateVariable".
I am new to groovy, so I think there must be an easy way to do this, because otherwise it seems that closures completely break the encapsulation of the private implementation done in the super class ... this seems to be a very common need (super class implementation referencing its own private variables)
I am using groovy 2.1.3
I found this to be a good reference describing how Groovy variable scopes work and applies to your situation: Closure in groovy cannot use private field when called from extending class
From the above link, I realized that since you have declared accessThisPrivateVariable as private, Groovy would not auto-generate a getter/setter for the variable. Remember, even in Java, private variables are not accessible directly by sub-classes.
Changing your code to explicitly add the getter/setters, solved the issue:
package com.test
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
int getAccessThisPrivateVariable() { accessThisPrivateVariable }
void setAccessThisPrivateVariable(int value ){this.accessThisPrivateVariable = value}
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
super.add(obj)
}
}
b = new ClosureScopeD()
b.doSomething("abc")
There is a simpler way, just make the access modifier (should rename the property really) to protected, so the sub-class has access to the property.. problem solved.
protected int accessThisProtectedVariable
To clarify on your statement of concern that Groovy possibly has broken encapsulation: rest assured it hasn't.
By declaring a field as private, Groovy is preserving encapsulation by intentionally suspending automatic generation of the public getter/setter. Once private, you are now responsible and in full control of how or if there is a way for sub-classes (protected) or all classes of objects (public) to gain access to the field by explicitly adding methods - if that makes sense.
Remember that by convention, Groovy ALWAYS calls a getter or setter when your codes references the field. So, a statement like:
def f = obj.someField
will actually invoke the obj.getSomeField() method.
Likewise:
obj.someField = 5
will invoke the obj.setSomeField(5) method.

Automapper and access to member variables

I have an mvc controller which has a helper class injected into it. I would like to convert from a viewmodel to a dto using automapper. most of the properties are simple mappings but one involves calling the helper class with a parameter from the viewmodel. Ideally I would want to do something like this:
Mapper.CreateMap<TheViewModel, TheDto>()
.ForMember(dest => dest.Url, o => o.MapFrom(src => _urlHelper.GenerateUrlFromUsername(src.Username)));
...but I cannot because I cannot access a non-static field.
What is the best approach?
EDIT:
OK, so I have a custom resolver but how do I hook this in to my IoC container?
public class CustomResolver : ValueResolver<TheViewModel, string>
{
private readonly IUrlHelper _urlHelper;
public CustomResolver(IUrlHelper urlHelper)
{
_urlHelper = urlHelper;
}
protected override string ResolveCore(TheViewModel source)
{
return _urlHelper.GenerateUrlFromUsername(source.Username);
}
}
Use a custom resolver in this case:
http://automapper.codeplex.com/wikipage?title=Custom%20Value%20Resolvers
Custom resolvers can be instantiated from a container, so you can get whatever instance fields of services you need.

Passing parameters to UserControl constructor in c# 2.0

Is there a way to pass the parameters to the LoadControl function when loading the user control dynamically?
I found a solution that uses reflection here
All you need to do is create a descendant of the UserControl class, add a default constructor and another constructor that takes your parameters. The parameterless constructor is necessary for designer support.
public class MyControl : UserControl
{
public MyControl() : base()
{
// do initialization stuff...
}
public MyControl(int parameter) : this()
{
// do additional stuff with parameter
}
}

Resources