inloop / androidviewmodel Goto Github PK
View Code? Open in Web Editor NEWSeparating data and state handling from Fragments or Activities without lots of boilerplate-code.
License: Apache License 2.0
Separating data and state handling from Fragments or Activities without lots of boilerplate-code.
License: Apache License 2.0
onRetainNonConfigurationInstance is deprecated since API 13, this should be replaced with a headless fragment with setRetainInstance(true) or the models should be kept in a singleton model manager.
Hi,
When you want to use this library with some kind of dependency injection aka Dagger 2, you have no control over creating instance of ViewModel
.
So I've made a little change in API. Instead of having abstract getViewModelClass()
, i'm having createViewModel()
defined on fragments / activities. Then i can use whatever I want to create my ViewModel
object. This is good for IOC as well as having non default construtors etc.
This could be also done with some hard tunning ViewModelProvider
(private constructor there), but this change to API looks way better for me. You can check it out at dozd@827b494
Try to research if UI testing of the library would be feasible. Tests would verify if the model is correctly retained and then removed in cases such as:
Possibly other cases...
Would you able to compile an apk demo?
It would be useful to have custom template for Android Studio something like this so you could simply generate Fragment/Activity (maybe option to generate newInstance for fragment), Model (with boilerplate code) and IView.
If the setModelView() is called inside onViewCreated(),the changes made to the View in the bindView method will be discarded when the View State is Restored.
changing setModelView() to onStart method will solve the issue.
I would I inject or get the context in the viewmodel.
There will be lots of statements and commands I will want to invoke in the viewmodel that
will need a context.
For instance this statement:
((App) getApplication()).inject(this);
How would I get that going in the viewmodel?
thanks!
Since jCenter repository is being deprecated, do you plan to move to maven central repository, so that existing projects can keep using your library? Thanks for the info!
Is it possible to have a View and a ViewModel which act as a parent class to a subclass View and ViewModel where the parent class and the subclass define different contracts (IViews)?
I tried to do that but without success.
I suggest to rename some life-cycle methods in AbstractViewModel.java to make it more consistent. I am talking especially about bindView, saveState and onModelRemoved. All these methods are dependent on Activity/Fragment life-cycle and it would be very nice to follow the same naming convention as Activity/Fragment's methods do.
Methods should be prefixed with "on" and the action should be described in the present tense, not the passive (e.g. onCreate).
So I suggest to rename the methods like this:
bindView -> onBindView
Similar convention to Fragment.onCreateView or onDestroyView. Eventually it might be also "onViewBound" like Fragment.onViewCreated or onActivityCreated.
saveState -> onSaveInstanceState
To make it consistent with Activity/Fragment naming convention.
onModelRemoved -> onDestroy
It is called when the fragment or view is already gone and destroyed so this name makes sense. Also, as opposite to "onCreate", it makes more sense than "onModelRemoved". Moreover, the word "Model" in the name might be a bit confusing, because it is about ViewModel and not Model, right?
What do you say? I think these changes would make the code better readable. Thanks.
Hi there,
Glad to see this library handles Android life cycle quite well and AndroidViewModel does prove itself a great VM framework.
From the architecture diagram, I was wondering is it possible the ViewModel would deal with business Model instead of actual data component(DB, WebService...). If possible, how can I extend the existing framework ? What's your opinion ?
Thanks for this timely lib!
Can you point me in the direction of other projects that use this lib.
I would like to see more variety and styles of how other devs are implementing the lib.
thanks!
Is fragment required for AVM to work? I followed all the steps and all works in Fragments but I created one ResetPasswordActivity which does not use a fragment and AVM is failing there.
public class ResetPasswordActivity extends BaseActivity{
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reset_password);
ButterKnife.bind(this);
setModelView(this);
getViewModel().setEmail(email); // setEmail method not found
}
}
@Override
public Class<ResetPasswordViewModel> getViewModelClass() {
return ResetPasswordViewModel.class;
}
BaseActivity:
public abstract class BaseActivity extends ViewModelBaseActivity
ResetPasswordViewModel
public class ResetPasswordViewModel extends AbstractViewModel implements ResetPasswordViewModelInputs {}
Have I forgotten anything?
Hi, I'd like to ask, how would you implement the MVVM pattern (using Google's databinding library) on the items of the RecyclerView?
Let's say, I have a fragment containing just a RecyclerView
. This is easy, (Fragment implementing let's say IMainView
; with MainViewModel
etc.). But imagine the items within the RecyclerView
. If they have more complex layout, eg. when there is a CheckBox
or a Button
, I want to delegate calls from those views to something that implements the IView
. Let me explain:
Say, we have this layout of the item:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.mvvm.viewmodel.ItemViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:orientation="vertical">
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@{viewModel.text}"
android:textColor="@color/primary_text"
android:textSize="18sp"
tools:text="Lorem ipsum dolor sit amet" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@{viewModel.detail}"
android:textColor="@color/secondary_text"
android:textSize="14sp"
tools:text="Lorem ipsum dolor sit amet" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:checked="@={viewModel.checked}"
android:onCheckedChanged="@{(cb, isChecked) -> viewModel.changeState(isChecked)}"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="T"
android:onClick="@{() -> viewModel.test()}"/>
</LinearLayout>
</LinearLayout>
</layout>
I have implemented the ItemViewModel
that extends the AbstractViewModel<IItemView>
; Easy. The problem is that I do not know where should I implement that IItemView
interface. I cannot do such thing in the fragment nor the activity. I saw that Petr Nohejl dealt with this problem by "binding" the *Click
callbacks within the ViewHolder
of his adapter.
I have no doubts that this approach is correct, but I am new to the MVVM and I chose this library to take the small steps with learning it and I find the architecture in his application an overkill for what I need now.
For the end, simple example of the usage of my layout (for testing and experimental purposes):
In my ItemViewModel
I have a field checked
that is of type ObservableBoolean
and represents what the name says. Next, in the layout I have this Button
that have the onClick
listener passed from the viewModel. The logic is that after I tap the Button
a Snackbar
would appear saying whether the checkbox is checked or not. Here is a snippet from the viewModel
:
public void test() {
getView().test(checked.get());
}
Where should I implement that view.test(boolean)
? I would really appreciate any idea on what is (your personal) best way of solving this.
Thank you
Hello.
Could you please describe on the wiki what is the preferred way to communicate between view-models for this library? Especially the important part is how to abstract communication with view-model lifecycle, e.g. how pass data and messages to view-models that have not been instantiated yet?
A straighforward solution is to store data that needs to be passed from one view-model to another to shared preferences or SQLite database that are then loaded when the target view-model is instantiated and send events via broadcasts but I don't see this as a nice and clean solution.
Another option is to use observable pattern managed in static Application context but there is no option to keep observable object state when application object is terminated.
Thank you for the library anyway!
Since there is no onResume() in the ViewModel, what is the correct way to check if PlayServices is available?
Greetings! I am new to Android & trying to adopt your AndroidViewModel into my project. I am currently stuck on building the project because ;
@nullable
private T mView;
throws the exception "cannot resolve symbol 'T'. Could you please guide me as to what I am missing? Any help will go a long way.....
Thank you.
-Remy
When working with nested fragments the screen ID is not unique, as nested fragments share the same Bundle
, and so the IDs override one another. I would encourage storing screenId as part of BaseViewModelActivity
(or the sorts of such).
I have this code operational and running beautifully if I might add, but it's running inside the view.
Which in this case is a fragment....
From EURUSDSequenceView:
rxBus.toObserverable()//
.compose(bindToLifecycle())
.ofType(EURUSDPercentD.class)
.map(new Func1<EURUSDPercentD, JSONObject>() {
@Override
public JSONObject call(final EURUSDPercentD event) {
return event.getEvent();
}
})
.subscribe(new Action1<JSONObject>() {
@Override
public void call(final JSONObject message) {
if (eurusdSeqViewIsVisible.equals("true")) {
incomingData = true;
Log.d(TAG, "From: EURUSDSeqView, Msg: " + message.toString());
......
How can I get that code operational inside the viewModel because once those streams come in there is manipulation of the view going on...visibility, changing colors, saving data to prefs/dbs etc, etc
OR
should I just leave the subscription inside the view and then call to the viewModel accordingly?
thanks!
A quick fix for ProxyViewHelper
for those of us that failed to create activities or fragments with generic types:
public class ProxyViewHelper {
@Nullable
public static Class<?> getGenericType(@NonNull Class<?> in, @NonNull Class<?> whichExtends) {
final Type genericSuperclass = in.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
final Type[] typeArgs = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
for (Type arg : typeArgs) {
if (arg instanceof ParameterizedType) {
arg = ((ParameterizedType) arg).getRawType();
}
if (arg instanceof Class<?>) {
final Class<?> argClass = (Class<?>) arg;
if (whichExtends.isAssignableFrom(argClass)) {
return argClass;
}
}
}
}
return null;
}
}
Hi, thank you for the lib. I am wondering, how I can access to associated Activity/Fragment from ViewModel class.
Imagine this simple use case:
How would you solve this? Or should "start a detail activity" action be delegated back to the activity/fragment via getView().startDetailScreen()?
I have a Fragment and a Viewpager (FragmentStatePagerAdapter) inside that. I'm trying to access the ViewModel of one of the child fragments (in Viewpager) from parent fragment. Its working fine but when orientation changes it crashes with "java.lang.IllegalStateException: ViewModel is not ready"
Why is this happening?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.