I have used LiveData and ViewModel example
but i dont understand use of this feature because i can change value directly without use this feature even this is growing number of line in code by using observing code and same as in ViewModel by creating MutableLiveData.
below ViewModel Code
public class FirstViewModel extends ViewModel {
// Create a LiveData with a String
public MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}
}
Using in Activity
public class MainActivity extends AppCompatActivity {
private FirstViewModel mModel;
ActivityMainBinding mBinding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding=DataBindingUtil.setContentView(this,R.layout.activity_main);
// Get the ViewModel.
mModel= ViewModelProviders.of(this).get(FirstViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
#Override
public void onChanged(#Nullable final String newName) {
// Update the UI, in this case, a TextView.
mBinding.mNameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
mBinding.btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String anotherName = mBinding.etField.getText().toString();
mModel.getCurrentName().setValue(anotherName);
}
});
}
}
The ViewModel and LiveData android architecture components together help to create lifecycle aware applications.
ViewModel:
ViewModel classes are often used to significantly segregate the view logic (present in Activity classes) from the business logic which is contained in the ViewModel classes. This segregation is a good architecture design and becomes very important while maintaining large projects.
LiveData:
LiveData helps in implementing the Observer Observable pattern in a lifecycle aware manner.
In your case, it may seem trivial since you are only setting value for a TextView. However consider common scenarios like hitting an api to retrieve data, etc. In such cases, the ViewModel is responsible for providing the data to be displayed in the Activity, which when done with the help of LiveData can help avoid crashes by ensuring lifecycle awareness easily.
You can read about live data from here. It is like Observer that looks for changing of data and notify observers that observable object has changed
In simple words its make your life eazy as a programmer when we go into the details like activity/fragment lifecycle handling, displaying updated data and more importantly separating the presentation layer from business logic and to create a more well structured application. please find more details from here
Related
I am bit stuck at understanding the relation b/w using viewmodel and livedata. I hope that someone can explain it for me. I am new to Android Development.
It's all well explained here. The ViewModel purpose is to manipulate the data so to provide the data needed to the view, like in any normal mvp pattern. LiveData instead is the (lifecycle aware) callback for the view model, so that any time the data set is updated (so the model has a potential change in its state), the execution flow is brought back to the model, so that the model can update itself, for instance manipulate the new data set before to provide it to the view. I hope it's clear
For MVVM architecture it looks like this: you create model with your data, you access and change it in view model(in instances of LiveData). And observe it in views(activities/fragments).
MainViewModel extends ViewModel{
MutableLiveData<String> someStringObject = new MutableLiveData<>;
private void someMethod{
someStringObject.setValue("For main thread");
someStringObject.postValue("For back thread");
}
public MutableLiveData<String> getSomeStringObject(){
return someStringObject;
}
}
FragmentA extends Fragment{
#BindView(R.id.tv) //ButterKnife
TextView someTV;
private MainViewModel mainViewModel;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
//getting viewModel
mainViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
//registering observer
mainViewModel.getSomeStringObject.observe(this, value ->{
someTV.setText(value);
});
}
}
This way you can react to changes of ViewModel in your View. Now if getSomeStringObject is changed in mainViewModel it will automatically change in FragmentA.
This question is centered around the architecture of an Android Application. When using the LifeCycle component ViewModel, is it best to have one ViewModel per fragment or one ViewModel for the parent activity, to which the Fragments are subscribed to?
It seems unclear to me how to orient something like a Master-Detail fragment-activity relationship without some coupling. For instance, if each Fragment had it's own ViewModel, it is unclear how the Activity should know how to react without coupling (interface, direct functions calls).
As I mentioned in the comments, there is no unique way to accomplish this, but ideally, and very specifically to your Master/Detail flow concern, let's analyze the default provided example:
ItemDetialActivity handles fragment creation and display, FAB and menu actions. Note that there is nothing related to user data, only "system" handles . I, for instance, try to limit activities responsabilities to navigation, and stuff you really can't avoid like menu button handling. Now, ItemListActivity appears to be violating this principle because takes care of displaying the list (Google examples only create confusion -IMHO- between these separation of concerns), I would create a separate fragment that contains the RecyclerView and its adapter.
Now to the nitty gritty. Here is a very high-level skeleton I hope you can make use of. Check it out, implement it, and come back if there are any questions:
public interface BaseView {
LifecycleOwner lifecycleOwner();
/* perform actions that affect a basic screen status, like hide/show progress bars and errors,
animate views, etc. */
}
public class BaseRepo {
// will contain LiveData instances which will postValues()
}
public class FooRepo extends BaseRepo {
/* will contain access to database and networking functions, either by creating instance methods
or enforcing with an interface, it's up to you. */
}
public class BaseModel<P extends BasePresenter> extends ViewModel {
protected final FooRepo fooRepo; // optional, can be on concretes
<T> void subscribe(LiveData<T> liveData, Observer<T> observer) {
liveData.observe(view.lifecycleOwner(), observer);
}
<T> void unsubscribe(LiveData<T> liveData, Observer<T> observer) {
if (liveData != null) {
liveData.removeObserver(observer);
}
}
...
}
public abstract class BasePresenter<M extends BaseModel, V extends BaseView> implements LifecycleObserver {
protected V view;
protected M model;
public void setModel(M model) {
this.model = model;
}
public final void attachView(V view, Lifecycle lifecycle) {
this.view = view;
lifecycle.addObserver(this);
}
public void setPresenter(P presenter) {
this.presenter = presenter;
this.presenter.setModel(this);
}
...
}
public abstract class BaseFragment implements BaseView {
/* generics is highly encouraged here, I've seen examples of both BasePresenter<P>
and BaseView<P> */
protected P presenter;
/* You should bind layers here, or in the concrete class,
either with Dagger, reflection, or some other way */
#Override
public LifecycleOwner lifecycleOwner() {
return this;
}
...
}
Now, for every concrete screen you should create a presenter, model, and fragment that derive from the bases, and perform specifics there. I hope it helps.
The suggested way to implement ViewModel is to expose the changing data by using LiveData objects to activities, fragments and views. There are cases, when LiveData is not an ideal answer or no answer at all.
The natural alternative would be, to apply the observer pattern to the ViewModel, make it an observable. When registering observers to the ViewModel, the ViewModel will hold callback references to notify the observers.
The documentation says, a ViewModel must not hold references to activities, fragments or views. The only answer to the question "why" I found is, that this may cause memory leaks. Then how about cleaning up the references to avoid memory leaks?
For views this is a difficulty. There is no defined moment, when the view goes away. But activities and fragments have a defined lifecycle. So there are places to unregister as observers.
What do you think? Is it valid to register activities as observers to ViewModels if you take care to always unregister them? Did you hit upon any valid information about this question?
I set a small reward for the best answer. It's not because I think it a recommended solution (as it does not work with views). I just want to know and extend my options.
public class ExampleViewModel extends ViewModel {
public interface OnEndListener {
public void onEnd();
}
private List<OnEndListener> onEndListeners = new ArrayList<>();
public void setOnEndListener(OnEndListener onEndListener) {
onEndListeners.add(onEndListener);
}
public void removeOnEndListener(OnEndListener onEndListener) {
onEndListeners.remove(onEndListener);
}
public void somethingHappens() {
for (OnEndListener onEndListener: new ArrayList<OnEndListener>(onEndListeners) ) {
onEndListener.onEnd();
}
}
}
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
ExampleViewModel.OnEndListener onEndListener;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onEndListener = new ExampleViewModel.OnEndListener() {
#Override
public void onEnd() {
finish();
}
};
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.setOnEndListener(onEndListener);
}
#Override
protected void onDestroy() {
super.onDestroy();
exampleViewModel.removeOnEndListener(onEndListener);
}
}
To ask "am I allowed..." is not really a useful question, IMO. The docs are clear that what you are suggesting is discouraged and why. That said, I expect that your code would probably work as expected and is therefore "allowed" (i.e. not prevented by a technical constraint).
One possible gotcha scenario: InstanceA of ExampleActivity is started and kicks off some long-running task on the ExampleViewModel. Then, before the task completes, the device is rotated and InstanceA is destroyed because of the configuration change. Then, in between the time when InstanceA is destroyed and a new InstanceB is created, the long-running task completes and your view model calls onEndListener.onEnd(). Except: Oh no! The onEndListener is null because it was cleared when InstanceA was destroyed and hasn't yet been set by InstanceB: NullPointerException
ViewModel was designed (in part) precisely to handle edge cases like the gotcha scenario above. So instead of working against the intended use of the ViewModel, why not just use the tools it offers along with LiveData to accomplish the same thing? (And with less code, I might add.)
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.getOnEndLive().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(#Nullable Boolean onEnd) {
if (onEnd != null && onEnd) {
finish();
}
}
});
}
}
public class ExampleViewModel extends ViewModel {
private MutableLiveData<Boolean> onEndLive = new MutableLiveData<>();
public MutableLiveData<Boolean> getOnEndLive() {
return onEndLive;
}
public void somethingHappens() {
onEndLive.setValue(true);
}
}
Think of the LiveData in this case not as actual "data" per se, but as a signal that you can pass from your ViewModel to your Activity. I use this pattern all the time.
Okay, so I just started a new Android project and wanted to try implementing the Clean Architecture by Uncle Bob. I have a nice beginning using RxJava and stuff from GitHub samples & boilerplates and Fernando Cerjas' blog (like this article), but still have some questions on how to implement some UseCases.
TL;DR
Should an Entity have fields that are another Entity (in my example, User having a List<Messages> field)?
Or should the Presenter combine UseCases to build a ViewModel mapped on multiple Entities (then how to you code the mapper?)?
Or should the Presenter have a ViewModel associated to each UseCase/Entity, and create some kind of "wait for all data to onNext" to call the view.show() for each ViewModel?
Basically, should UseCases only return Entities? Can an Entity be composed of other entities (as in a field of the class)? Are Entities only dumb datamodels POJOs? How to you represent 'join SQL' queries?
As an example, let's take a simple users/messages app.
I want to implement two views: UserList and UserDetails:
UserList displays a list of Users
UserDetails displays a user's information and its latest messages.
UserList is pretty straightforward, and I can see how to code the associated UseCase and layers (code below).
My problem is with the UserDetails screen.
How should I code my GetUserInfoUseCase if I want all the data to be passed at the view at the same time (like building a ViewModel composed of a User class, with a field List)? What should be the return value of the GetUserInfoUseCase?
Should I code a Observable<User> GetUserInfoUseCase and a Observable<List<Message>> GetUserLatestMessages and merge them somehow in my presenter? If yes, how can I manage this, as I don't have the Observables in my Presenter (I'm passing only an Observer as my UseCases parameters)?
User Entity
public abstract class User {
public abstract long id();
public abstract String name();
...
}
Message Entity
public abstract class Message {
public abstract long id();
public abstract long senderId();
public abstract String text();
public abstract long timstamp();
...
}
GetUsersUseCase
public class GetUsersUseCase extends UseCaseObservableWithParameter<Boolean, List<User>, UsersRepository> {
#Inject
public GetUsersUseCase(UsersRepository UsersRepository,
#Named("Thread") Scheduler threadScheduler,
#Named("PostExecution") Scheduler postExecutionScheduler) {
super(usersRepository, threadScheduler, postExecutionScheduler);
}
#Override
protected Observable<List<User>> buildObservable(Boolean forceRefresh) {
if(forceRefresh)
repository.invalidateCache();
return repository.getUsers();
}
}
UsersPresenter
public class UsersPresenter extends BasePresenter<UsersContract.View> implements UsersContract.Presenter {
#Inject
GetUsersUseCase mGetUsersUseCase;
#Inject
UserViewModelMapper mUserMapper;
#Inject
public UsersPresenter() {
}
#Override
public void attachView(UsersContract.View mvpView) {
super.attachView(mvpView);
}
#Override
public void detachView() {
super.detachView();
mGetUsersUseCase.unsubscribe();
}
#Override
public void fetchUsers(boolean forceRefresh) {
getMvpView().showProgress();
mGetUsersUseCase.execute(forceRefresh, new DisposableObserver<List<User>>() {
#Override
public void onNext(List<User> users) {
getMvpView().hideProgress();
getMvpView().showUsers(mUsersMapper.mapUsersToViewModels(users));
}
#Override
public void onComplete() {
}
#Override
public void onError(Throwable e) {
getMvpView().hideProgress();
getMvpView().showErrorMessage(e.getMessage());
}
});
}
}
UseCaseObservableWithParameter
public abstract class UseCaseObservableWithParameter<REQUEST_DATA, RESPONSE_DATA, REPOSITORY> extends UseCase<Observable, REQUEST_DATA, RESPONSE_DATA, REPOSITORY> {
public UseCaseObservableWithParameter(REPOSITORY repository, Scheduler threadScheduler, Scheduler postExecutionScheduler) {
super(repository, threadScheduler, postExecutionScheduler);
}
protected abstract Observable<RESPONSE_DATA> buildObservable(REQUEST_DATA requestData);
public void execute(REQUEST_DATA requestData, DisposableObserver<RESPONSE_DATA> useCaseSubscriber) {
this.disposable.add(
this.buildObservable(requestData)
.subscribeOn(threadScheduler)
.observeOn(postExecutionScheduler)
.subscribeWith(useCaseSubscriber)
);
}
}
UseCase
public abstract class UseCase<OBSERVABLE, REQUEST_DATA, RESPONSE_DATA, REPOSITORY> {
protected final REPOSITORY repository;
protected final Scheduler threadScheduler;
protected final Scheduler postExecutionScheduler;
protected CompositeDisposable disposable = new CompositeDisposable();
public UseCase(REPOSITORY repository,
#Named("Thread") Scheduler threadScheduler,
#Named("PostExecution") Scheduler postExecutionScheduler) {
Timber.d("UseCase CTOR");
this.repository = repository;
this.threadScheduler = threadScheduler;
this.postExecutionScheduler = postExecutionScheduler;
}
protected abstract OBSERVABLE buildObservable(REQUEST_DATA requestData);
public boolean isUnsubscribed() {
return disposable.size() == 0;
}
public void unsubscribe() {
if (!isUnsubscribed()) {
disposable.clear();
}
}
}
Quite a lot questions within a single question. let me try to consolidate what I think I understood are ur key questions
Can Entities reference each other? the answer would be: YES. Also in
Clean Architecture u can create a domain model where entities are interconnected
What should be returned from a UseCase?
Answer: UseCases define input DTOs (Data transfer objects) and output DTOs which are most convenient for the use case. in his book uncle bob writes that entities should not be passed to use cases or returned from use cases
What is the role of the presenter then? Answer: ideally a presenter is converting data only. It converts data which is most convenient for one layer into data which is most convenient for the other layer.
hope this guidance helps u to answer ur detailed questions
More details and examples you can find in my recent posts:
https://plainionist.github.io/Implementing-Clean-Architecture-UseCases/
and
https://plainionist.github.io/Implementing-Clean-Architecture-Controller-Presenter/
Basically, you want to push your "instrumental" aware code as far as possible (on the circle).
Use cases are very close to the model and contain a lot of business logic - you want this layer very clean to be able to do quick and easy unit tests. So, this layer shouldn't know anything about storage.
But the fun part is when Room enters the room :) Room makes it so easy to have model-like objects that you can use around and IMO it's a grey area should you use Room annotated classes for your model or not.
If you think about Room objects as Data Layer objects, then you should map them to your business objects before reaching use cases.
If you use Room as a built-in mapper of DAO to model objects, then IMO you can use them in your use cases, although clean purists probably would not agree on this.
My pragmatic advice would be - if your model has a complex structure built in from multiple entities then have a dedicated model class for it and map entities to it.
If you have something like an Address, IMO just go with the Room entity.
I have a service which provides UI that is visible to user most of the time.
I was experimenting with new Application Architecture when I came with a problem.
MyModelviewModel viewModel = ViewModelProviders.of(this).get(MyModelviewModel.class);
But as you know this can be only AppCompat or Fragment
Is there some alternative? or can I put observer directly on my LiveData like Im puting on ViewModel
viewModel.getList().observe(Playground.this, new Observer<List<TestEntity>>() {
#Override
public void onChanged(#Nullable List<TestEntity> items) {
recyclerViewAdapter.addItems(items);
}
});
LiveData can be use independently without ViewModel,you can use observeForever(Observer<T> observer), or observe(LifecycleOwner owner, Observer<T> observer) while you provide a proper LifecycleOwner instance, you can implement LifecycleOwner in your service or view.
ViewModelProviders just provides a cache of ViewModel for each Fragment or Activity, you can create your ViewModel directly by new MyModelviewModel().
Initialize with
new ViewModel()
in
onStartCommand