I have searched for some similar questions before posting - however I have a general question when it comes to Android and data binding (and the other answers I check did not really get me much further...). Assume you have a class Vehicle:
public class Vehicle {
private Owner owner;
private String brand;
//getter and setter for above attributes...
}
and here is the Owner class ....
public class Owner {
private String name;
}
Now - I was just recently looking into MVVM (ModelView-ViewModel) pattern as employed by Microsofts WPF. Which got me wondering: Assuming I would want to bind the name property of my owner object which is a child of the Vehicle object - would there be some standard way in Android to achieve this? Also presuming, that I might have to validate input before I can have the Model updated?
I was imagining the following components (assuming MVVM):
The View (an Activity) contains no application logic - so its more or less empty
A ViewModel would handle the instance of the Vehicle object and perform actions on it
The Model itself would look as the code I posted before - totally oblivious to the View
and the ViewModel
Now when I add my EditTexts, TextViews and so on to the view, I want them to bind to certain the properties of my context object (Vehicle in this case) ... Mhhh if my question is not clear or you need further informatio do let me know :) thanks in advance.
P.s. I think people familiar with WPF might now what I mean? I myself just read about WPF and found it's a nice way to handle stuff.
P.P.s I am aware of the android binding project but I was wondering if there is a sort of build-in approach in Android or maybe some convention someone is following :) this really is more of a binding-theory question I guess ...
Native Data Binding
Google has launched its native Data Binding Library!
https://developer.android.com/tools/data-binding/guide.html
Which lets you write your views as such
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.firstName}"/>
But its event wiring mechanism at this time (rc1 version) can't bind to methods on a class extending from Observable (an exception is thrown when compiling; this is a known bug which will be solved).
And sure the lack of two-way binding (which is not expected to be on the first release) is a big drawback.
Anyway, here's a good sample project to play around with https://github.com/saleeh93/data-binding-samples
There is nothing "baked" into the Android SDK which provides equivalent databinding functionality found in MS WPF. Google is providing a lower level interface for the various devices running Android. To date, higher level application frameworks have not emerged from the Android development community. (IMHO, it would take a monster company like Google to create such a thing, given all the different constraints on a framework for all the various Android devices.)
You could create a set of databinding classes in your own application to handle your needs for the MVVM pattern. The "Databinders" would set the relevant event handlers on Android View objects and run some appropriate method on your ViewModel objects in response. They would also translate change events (that you define) on the ViewModel into the appropriate property assignments on the View objects.
Whether that turns out to be worthwhile for your application is a judgment call. My guess is that it would require more effort to write the Databinder classes than just to hook the lower level View event handlers directly. Frameworks are useful primarily when you didn't have to write them yourself.
Well, my Android-Binding project is trying to do data-binding via XML layout. Because there's no build-in method provided by Google (and I can't foresee that Google will do so), that's the reason I started this project.
Android M will provide powerful library for data binding!
It's available now in dev-preview version.
It looks amazing inside xml and java files:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.firstName}"
/>
Java bean:
public class User {
private final String firstName;
private final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
Binding:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);
}
Reading a bit about this topic, I just found RoboBinding, a "data-binding Presentation Model framework" for Android.
Similar to the Android-binding project, you can bind properties (one-way or two-way) and events to your views in XML using an extra namespace.
Although it is no built-in approach either, it might be a great help for you.
Since you first asked your question, the landscape has changed a lot.
Most importantly Stuart Lodge gave us MVVMCross.
This project provides a cross-platform mvvm mobile development
framework built on top of Silverlight for WP7, Mono for Android and
MonoTouch for iOS, and the WinRT XAML framework for Windows 8 Store
applications
This project makes extensive use of Portable Class Libraries to
provide maintainable cross platform C# native applications.
It provides data binding in your Views against ViewModels
For example, it enables the following:
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="{'Text':{'Path':'Query','Mode':'TwoWay'}}" />
Resources:
Github Page:
https://github.com/slodge/MvvmCross
Presentation:
http://slodge.blogspot.co.uk/2012/12/mvvmcross-video-presentation-xaminar.html
And a very good introductional tutorial: Building Android Apps with MVVM and Data Binding
In addition to Oleksii's answer, for those who want to see a sample project (it seems Google hasn't provided any sample project yet), I just made one and pushed it to GitHub.
A few notes:
classpath "com.android.databinding:dataBinder:1.0-rc0" doesn't work for me so I use classpath group: 'com.android.databinding', name: 'dataBinder', version: '1.0-rc0'
Need Java 7 +
If you get errors, try clean/rebuild.
Don't forget to implement android.databinding.Observable or extends BaseObservable if you need the ability to notify when data changes.
minSdkVersion is 7. It's a support lib.
My project doesn't follow MVVM, it just uses data binding. Added MVVM sample.
I realize this is some years later but faced with the same issues I ran across the following which may help lessen the load.
RoboBinding - handles binding - as mentioned above
RoboGuice - does dependency injection
There is a very nice video presentation of RoboBinding that will help explain what and how.
I am not affiliated with either effort but they do look promising for those folks still trying to resolve the binding issues, especially on involved code. RoboBinding also handles bidirectional updates.
Related
I am using MVVM android architecture for my application.
I want to implement click event, so, do we need to use data binding architecture components or we can just use activity for handling the click event and validating the user inputs?
What's the best way to implement this?
Well the question would be using the Databinding or not. Here are some pros and cons of Databinding:
Pros:
Makes the code super clean.
Makes the code shorter.
Easy to test.
Cons:
Sometimes it's hard to debug.
It's a little heavy and increases the compile time.
But... since Google has already anounced it as part of the Android Architecture components I believe you should use it.
What's the best way to implement this?
I don't know how familiar you are with the Databinding but you should know something about Binding Adapters, anw in the onClick you won't be needing it. Just add the android:onClick attribute in the XML file. Also you can find this Codelab to properly implement it:
https://codelabs.developers.google.com/codelabs/android-databinding/#0
Example:
First of all make sure you have the Databinding enabled in your build.gradle
android {
...
dataBinding {
enabled true
}
}
After that go to the layout you will use the databinding (and for that make sure it will be an Activity/Fragment), and just type ALT+ TAB in your IDE and than....
After that, define types, for example a ViewModel and it's name. And in the view that will use the click function add what I said above. (android:onClick="#{() -> viewmodel.onLike()}")
You are not finished. You will somehow need to connect your logic to that databinding, so go to your Java/Kotlin code for your Activity/Fragment and:
Replace the setContentView(R.layout.some_activity) with val binding : SomeActivityBinding =
DataBindingUtil.setContentView(this, R.layout.some_activity)
Notice the SomeActivityBinding will be provided by the IDE itself because is handled on the Databinding library according to the xml naming.
That's the most basic. Good luck.
Where can i find a detailed list of the naming conventions of MvvmCross?
I came across this Stack-Overflow Thread but the wiki seems to be disabled.
Also, the official documentation isn't in-depth enough.
I recognized some strange behavior, for example, if I add a new layout without any view / viewmodel class, the app will crash at startup. So does it if i do not start a view models name with "view_".
It took a few hours to find out that the MvvmCross seems to do some magic stuff with layouts at the startup depending on their names, even if they aren't used in code or don't have any view models.
Refer to official mvvm cross documentation:
https://www.mvvmcross.com/documentation/getting-started/mvvmcross-overview
One important thing to note, is that by default Views are associated
with ViewModels using a naming convention. But using generic is the
preferred way. On iOS for example, this is what a View class
declaration would look like:
public class MyView : MvxViewController
What other conventions do you have in mind? I found a copy of the missing wiki here https://github.com/rafaelsteil/MvvmCross-Wiki/blob/master/Customising-using-App-and-Setup.md
I'm creating a new module in android studio, and I want some of the classes to be hidden to outside of the module, I mean, that the classes could just be used internally in the module, but not externally. Is it possible? How could I achieve that?
Thanks in advance!
EDIT: I doubt it's possible to have module-visibility, but the closest you can use is package-visibility, for which you do the following:
Don't make the classes you intend to hide 'public'. Keep the default visibility, which is only seen within classes of the same package. Other public classes within this same package can act as your external interface to your module.
class PrivateToPackageInModule {
}
public class InterfaceOfModule {
private PrivateToPackageInModule ptpim;
}
For anyone that happens to stumble upon this post, there is now a keyword called internal which offers exactly the functionality that OP was looking for.
Documentation link
I've read about MVP design pattern and have some question about it.
If we consider Android SDK we can suggest that an Activity is a Presenter which takes over event handling, lifecycle events executing and communication with data-layer which can be a SharedPreferences, SQLlite etc. View in that case is just xml- view description which doesn't contain any event handlers or other user-communication things.
But I'm doubt if my reasoning correct at all? Could you help me to understand?
Android also follow MVC architecture.
1) In Android activity is the controller where you write a code for handling input & response.
2) xml layouts represent the view where you describe the presentation part of the application.
3) & model is your java pojo classes. For instance Person class which has two attributes first name & last name.
I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.