I know that I can expose a "jsBridge" object to javascript in webview by
Control.AddJavascriptInterface(new JsBridge(), 'jsBridge');
It seems inside the "JsBridge" class, we can only expose methods like
[JavascriptInterface]
[Export("myMethodName")]
public void MyMethod(string message)
{
//some logic
}
But I need some way to expose some objects or properties like bellow:
public ApiModule1 Module1 => _module1;
public ApiModule2 Module2 => _module2;
seems the "ExportAttribute" can only be applied to methods.
I am doing this because I need a way to expose only one single namespace at the JavaScript side, and still keep things organized by not stuffing everything into one object, that is;
jsBridge.Module1.someMethod();
jsBridge.Module2.someMethod();
Did I misunderstood some concepts here or is there are any other way to achieve this kind of feature?
Thank you very much.
You cannot expose properties directly. If you want to export any object create a getter for same in the interface you are exposing.
Related
Recently at my company a debate started after reviewing a different approach for writing heavy duty classes.
A big Java class holding component specific logic (no standard OOP principles made sense) had to be rewritten in Kotlin. The solution provided was splitting the logic in categories and the categories into separate files with internal extension functions to the main class.
Example:
Main.kt
class BigClass {
// internal fields exposed to the extension functions in different files
// Some main logic here
}
BusinessLogic.kt
internal fun BigClass.handleBussinessCase() {
// Complex business logic handled here accessing the exposed internal fields from BigClass
}
What are your thoughts on this? I haven't seen it used anywhere maybe for a good reason, but the alternative of thousand lines classes seems worse.
You have to consider that an extension function is nothing more than a function with an implicit first parameter which is referenced with this.
So in your case you'd have something like:
internal fun handleBussinessCase(ref: BigClass)
which would translate to Java as:
static void handleBussinessCase(BigClass ref)
But this could be assumed to be a delegate pattern, which could be encapsulated much cleaner in Kotlin as well.
Since the properties have to be internal anyhow, you could just inject these as a data class into smaller use-cases. If you define an interface around these (which would make the properties public though), you could create a delegate pattern with it and still reference each property with this in your implementation.
Here are some thoughts on making extension functions for the class:
It will be a utility function that will operate with the object you're extending, it will not be an object function, meaning that it will have access to only public methods and properties;
If you're planning to use class that being extended in unit tests, these methods (extensions) will be harder to mock;
Most likely they wont behave as you expect when used with inherited objects.
Maybe I missed something, so please read more about extensions here.
I have created a custom view in android. one of the methods has a signature like this:
fun show(CategoryFilterModel model) {/*...*/}
and it works fine. and now i'd like to create a overloaded function which would look like this if i did it by adding it to the custom view class:
fun show(ShopFilterModel model) {/*...*/}
Notice the type is different so this is a method overload.
a thought came to me that i could instead use an extension in kotlin to add another method to the class.
so it would like something like this:
fun MyCustomView.show(ShopFilterModel: model){
}
is this advised or should i only add utility methods with extensions ? Are there any overheads ?
It’s not only for utilities, as you can read in this great answer, which lists pretty much all use cases.
Imho, if you have control over that class you want to extend with a method, there’s no problem to add the method directly to it as opposed to doing it with an extension method. Yet, technically you can consider doing this. Please be aware that calling such an extension function from Java isn’t very idiomatic because it will be compiled to a static function. If it’s ever going to be invoked from Java, I’d rather use ordinary methods when possible.
I'm developing an android app implementing MVP and clean architecture. I have the following scenario:
One core module with presenters and view interfaces,...
One domain module with repositories, data sources,..
App module with the core implementation (so the Fragment/Activities).
Currently the strings.xml file is in the app module, but I'm thinking whether it should be in a commons module or not. The problem is that, sometimes, the presenter must set the text to the view, so the presenter should need to access to the strings.xml. I've thought in two possible solutions:
1) Create a TextHelper interface on core module that will be implemented on the app module and injected to the presenter, so the presenter will use this helper to get the strings it requires. (This is the solution I have implemented).
2) Move the strings.xml file to a common module so the file can be accessed from core module. But this solution would have a problem: the presenter doesn't have a context.
What do you think? What is the best approach?
Thanks in advance
If your view has nested if/elses related to strings, then they should probably be unit-tested. Therefore, that logic should stay in presenters or use-cases, where can be tested more quickly.
Your question is about how to retrieve the actual strings, given that they reside in the "outer layers" of the Clean Architecture scheme, i.e. in the Context object. IMHO your TextHelper is the right approach, as it allows to inject a mock when writing unit tests: you're interested in how the strings are processed, rather than how the strings actually look. I'm trying a very similar approach and calling it StringsRepository.
A point of uncertainty is how the the repository API should look like:
A single method like getString(#StringRes int stringResId, Object... formatArgs) that simply wraps Context.getString(): very simple to implement, but will make the presenters depend on your R.string class, which in turns requires strings.xml to be in the same module as your code under test;
One method per string with optional arguments, each one containing the reference to the appropriate string ID. This solution allows for best abstraction, but may become big (both the interface and the implementation...) and many domain classes may depend upon it. Handle with care.
Like (2), but with several classes, one per each part of your app. Each class may have a base class similar to (1) but with that method with protected visibility.
The best options for your case would be (2) or (3), but your mileage may vary.
You can use Application class to get the context any where from the app.
public class MVPApplication extends Application {
private static Context context;
public static Context getContext() {
return context;
}
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
I'm trying to persist data objects throughout my Android app. I want to be able to access an object in one activity, modify it, save it, navigate to a new activity, and access the same object with the updated value.
What I'm essentially talking about is a cache, but my data objects are complex. For example, ObjectA contains ObjectB which contains ObjectC. Does anyone know if a good method, tool, or framework for persisting complex objects in Sql?
Put a static field in a subclassed Application. Also inside your manifest, put:
android:name="MyApp" inside your application tags.
Also to access from other files, simply use:
MyApp myApp = (MyApp)getApplicationContext();
See here How to declare global variables in Android?:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
You could use an ORM framework, like OrmLite for mapping objects into sql, but it may be an overkill for you situation.
You could also make these shared object Parcelable and pass them between the Activities thru the Intents.
You could also save these objects into the SharedPreferences, so each Activity can access them whenever they feel the need to it, and the objects are also persisted this way. This may mean more IO access though, so take that into consideration as well. You could use e.g. Gson to serialize the objects more painlessly for this.
These are the solutions I'd consider. But whatever you do, don't put this common object into some kind of "standard" global static variable, like using a custom Application class, static field or any implementation of the Singleton pattern, these are really fragile constructs on Android.
Why don't you use a JSON serialization mechanism ?
In association with a static access to your objects you can easily build a lite-weight database with some basic functionnalities:
loadObjectsFromCache
saveObjectsInCache
getObjects
You can also store your objects in differents files, and use a streaming json parser like this one: http://code.google.com/p/google-gson/
It's the same that this one: http://developer.android.com/reference/android/util/JsonReader.html
but can be used even if your application api level is inferior to 11.
It use less memory than the basic DOM parser:
http://developer.android.com/reference/org/json/JSONObject.html,
but with the same speed.
I'm starting to work with the android system and Java in general.
I'm coming from a VB background, and in VB I had a Module, that enabled me to write functions that were accessible from everywhere in my program(different pages for example)
Is there something similar to the Module of VB6 in Java and Android?
Thanks!
In Java you can set the visibilty of a function to public. Then you can access it from everywhere in your code, if you have a object of that class.
public void doSomething() {
}
Then you can also use the keyword static to define methods that do not need to be called from an object of that class but exists during the first loading of the class until the end of the programm:
public static void doSomething() {
}