JniHandleOwnership in Mono for Android - android

Can someone explain to me what the exact meanings of the three JniHandleOwnership enum values in Mono for Android are? What's the difference between them?

My apologies for not updating the class library documentation yet.
The Binding Android Types documentation states what the various JniHandleOwnership values mean in the Wrapping with Java.Lang.Object section.
Update based on comments:
JniHandleOwnership.DoNotTransfer should be used if nothing should be done with the handle parameter. This should always be used within connector methods.
JniHandleOwnership.TransferLocalRef should be used when you have a local reference (e.g. you called JNIEnv.CallObjectMethod(), which returns a local reference) and you want to pass ownership of the local reference to a wrapper.
JniHandleOwnership.TransferGlobalRef should be used when you have a global reference and you want to pass ownership of the global reference to a wrapper:
IntPtr grefFoo = JNIEnv.FindClass("Foo"); // FindClass() returns a gref
var Foo = Java.Lang.Object.GetObject<Java.Lang.Class>(grefFoo, JniHandleOwnership.TransferGlobalRef);

Related

how to pass function as prop to aar in android

I develop the flutter package and in this package one of class get function argument.
When I use this package in another flutter app, I can send function as prop to this package .
Now I just want to learn if I use the flutter module and build the aar , how can I send function as prop in native android ?
Thanks
This is not possible because you can send only serializable types
By default, AIDL supports the following data types:
All primitive types in the Java programming language (such as int, long, char, boolean, and so on)
Arrays of primitive types such as int[]
String
CharSequence
List
All elements in the List must be one of the supported data types in
this list or one of the other AIDL-generated interfaces or parcelables you've declared. A List may optionally be used as a parameterized type class (for example, List). The actual concrete class that the other side receives is always an ArrayList, although the method is generated to use the List interface.
Map
.
All elements in the Map must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. Parameterized type maps, (such as those of the form Map<String,Integer>) are not supported. The actual concrete class that the other side receives is always a HashMap, although the method is generated to use the Map interface. Consider using a Bundle as an alternative to Map.
For more detailed information you can refer to the official AIDL documentation

How to rename realm object in iOS

I am using realm in our iOS and Android app. For some reason i want to rename one of my realm object.
Initially we name the object Demo and now I want to change it to RealmDemo
In android we achieved it by using #RealmClass annotation
#RealmClass(name = "Demo")
open class RealmDemo : RealmObject() {
}
On iOS side i am not sure how exactly i can do similar as i did in android.
class RealmDemo: Object {
override static func className() -> String {
"Demo"
}
}
I tried above ^ but getting following error "Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'Demo' not managed by the Realm'"
Two things.
First, You can name an object anything you want and change its name at any time.
HOWEVER, that's a destructive change, and Realm doesn't have any way to know the the newly named object 'is the same object' as the prior object.
How that's handled depends on what the use case is:
If this is a development situation, delete your local Realm files and run the app and the object with the new name will be created automatically.
If this is production then a migration block is needed (as on any platform) to migrate the data from the old object to the new one.
Secondly, The other important thing is the name of the object is now RealmDemo, whereas the prior object is Demo
class RealmDemo: Object {
so technically those are two separate objects. To Realm, you've abandoned the Demo object totally and that's a destructive change. Demo is still hanging around but is not referenced in your code so an error is thrown
On a possibly unrelated note, the className function references Demo
override static func className() -> String {
"Demo"
}
But the object name is RealmDemo.
It's not clear why the className function exists but it's not required or really needed. See the documentation for objects to get a feel for their structure - they may need a Primary Key
Seems like realm does not support className overriding for cocoa/ios.
https://github.com/realm/realm-cocoa/issues/2194
https://github.com/realm/realm-cocoa/issues/6624

How to integrate Kotlin inline class with Android data binding?

Kotlin introduced inline class which is strong typed type alias. This can be useful when use with database. For example,
inline class Age(val value: Int)
inline class Height(val value: Int)
When they are written to database, they are compiled to Int but Kotlin can prevent you accidentally putting a Height into a Age Field. If you use type alias or Int directly, it is possible with type alias but inline class produces a compile time error.
However, these also cause problems with Android data binding. I get data binding error when I try to bind a String inline class to a String attribute.
While it is possible to write some kinds of adapter to bypass this, but it defeat the purpose of using inline class and not practical for creating adapters for all inline classes.
I would like to ask are there any elegant ways to solve this issue?
First thing you need to understand is inline classes are not just wrappers around primitive types. They are more than type Aliases.
Now coming to your example, even though DataBinding has the understanding that if you put any MutableLiveData<T> instance in xml, it will take that value of that particular variable(something like mutableLiveData.value). But if you put MutablLiveData<Age>, mutableLiveData.value will always be of Type Age but not type Int.
Note that inline class, creates a completely new type and not just a type alias.
I believe that you somehow need a method in your data binding, that returns the value contained in the inline class object.

Kotlin Extension functions to split big classes

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.

Android native strong pointer vs std::shared_ptr

I'm referring to Refbase.h, Refbase.cpp and StrongPointer.h
In the Android implementation of strong pointer, any strong-pointer based object must inherit refbase i.e.
sp<TheClass> theObj // TheClass must inherit from class RefBase
This requirement can be seen in the code for one of sp's methods:
template<typename T> sp<T>& sp<T>::operator =(T* other) {
if (other != NULL) {
other->incStrong(this);
}
if (mPtr != NULL) {
mPtr->decStrong(this);
}
mPtr = other;
return *this;
}
In order for call to incStrong or decStrong to not fail . . . other and mPtr must have inherited RefBase
QUESTION
Why is sp implemented such that the obj that it's managing is required to be a child of RefBase? There's not even a way to enforce this requirement at compile-time or even runtime. (Well maybe if(type()...)
Std library doesn't have such a requirement
...
Upon further thought, is the answer that this provides flexibility?
If yes, how does this provide flexibility?
It saves a memory allocation. When you write:
std::shared_ptr<Foo> pFoo{new Foo(bar)};
pFoo actually has a pointer to a shared data structure (allocated on the heap), which has the reference counters, and the pointer to the actual Foo object. By making objects be derived from RefBase, you can embed the reference counts in the object itself (saving the additional memory allocation).
Interestingly, with C++11 onwards, you can avoid the additional memory allocation by using std::make_shared<Foo> which will do a single memory allocation and construct the shared data structure and the Foo object in it.
The fact there is no compile time checking of the derivation from RefBase is carelessness. m_ptr should have been declared as RefBase *m_ptr, and then operator * (etc) should have done a static_cast to T*. In fact, I would probably have made sp<T> inherit from sp_base which had the comparison operators as public, and the other functions as protected.
Edit
On second thoughts, there is quite a bit of compile time checking. If T doesn't have an incStrong member, the compilation will fail, and it almost certainly won't unless it derives from RefBase. I still think converting a T* to a RefBase* would have been a better check, but the one that is there is probably good enough.
It automatically allows you to create sp from any object implementing RefBase, while for shared pointer you can shoot yourself in the foot while trying to wrap raw pointer into shared one.
So while for shared_ptr you might need this:
http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
for sp you can almost safely pass raw pointer to sp contructor.

Categories

Resources