I was reading an article by Dario Miličić regarding MVP here. I also thoroughly went through the code he provided on git hub. Anyways, i am pretty new to MVP for android and MVP in general, and so I have a question about what he said - "The implementation layer is where everything framework specific happens”. What if i have an android application that deals with Bluetooth? i.e. i have a small application to get a list of bluetooth devices using BluetoothAdapter which is an android class. So I started writing a use cases which was something like this
public interface BluetoothScanInteracotor {
interface View {
void onScanStarted();
void onScanCompleted();
}
void scanForDevices();
}
but then realised that I cant do that because of its framework specific.
How would I go about this?
Forgive me if that's a silly question, but I might be confused about something and I need someone to help me understand.
The CLEAN approach would be to implement a BluetoothDeviceRepository, which could have multiple implementations, one of which would actually access the system resources, but could easily be swapped for one with no external dependencies for test, etc. The Bluetooth device scan results would be converted by repository implementations to return POJO models that represented the information you needed, so that there would be no leakage of the Android system classes into this layer.
The issue with most MVP implementation out there is that they designate Activities and Fragments as Views, and propose to use "Android framework independent" presenters.
This sounds good until one encounters issues like yours - Bluetooth framework is part of Android framework, so it is not clear how to use it in the presenter that shouldn't depend on Android specific classes.
After researching MVx architectures on Android for several years I realized that the only sane conclusion that can be derived is that Activities and Fragments are not views, but presenters.
The more detailed discussion of this subject can be found here: Why Activities in Android are not UI Elements.
Based on this idea I proposed an alternative implementation of MVP in Android: MVP and MVC Architectures in Android.
I have an idea in MVP model that not bad to share with you,
Everything that depends on the OS,should be treated as View, and Logic is Presenter,
For example Activity is a View, we use it to intract with UI ,for example get Text of a Textview, and when we need to process on the text, we make a presenter class for this activity and also an interface to this presenter, then implement the interface in presenter,and call methods of interface in Activity with needed params(for example that Text)
If I want implement it in another OS, i should only change my Activity and get Text in other way,and remain process is same and doesn't change
As you have come to know basics of Clean Architechure. The following example depicts how actual your MVP pattern is implemented.
Example:
interface BaseContract {
interface BaseView {
//Methods for View
void onDoSomething();
}
interface BasePresenter {
void doSomething();
}
}
class BaseMainPresenter implements BaseContract.BasePresenter {
BaseContract.BaseView view;
BaseMainPresenter(BaseContract.BaseView view) {
this.view = view;
}
#Override
public void doSomething() {
if (view != null)
view.onDoSomething();
}
}
class DemoClass implements BaseContract.BaseView {
//Create object of Presenter
/****
* Example :
* BaseMainPresenter baseMainPresenter = new BaseMainPresenter(this);
*/
#Override
public void onDoSomething() {
//Deal with Context here.
}
}
Related
I am using MVP patterns in Android. And structure looks like below.
Activity - Presenter
|
Fragment
|
CustomView
|
views
So when the presenter gets data from the network, it directly passes data to fragment, and fragment pass data to a custom view and custom view pass data to views.
I am not sure how I can pass data used in views from activity with MVP patterns. If I make presenters for each fragments, custom views, and views, then how can I pass data from activity's presenter to other presenters?
Anyone can help me out with examples?
In order to give a more specific answer to your question you need to give a concrete example. Every solution is valid in a context. I'll give couple of ways you can do this. Choose the one that suits your problem.
Very important part of the MVP is the Model. As far as I'm aware the term Model became popular in programing with the release of the paper Thing Model View Editor which was later refined and renamed to MVC.
The definition of the concept of a Model from this paper is:
A Model is an active representation of an abstraction in the form of
data in a computing system
The Models are represented in the computer as a collection of data
together with the methods necessary to process these data.
With time and experience, people have discovered and specified different types of models.
Here are some of them:
Domain Model
Application Model (read this article for more information)
Presentation Model
MVP, since it derives from MVC, makes two major divisions of responsibilities: Model (the abstraction that represent concepts) and Presentation (View and Presenter to visualize the Model).
Because we have divided the Model from the Presentation, we can have multipe Views that show the same Model different ways. An example of that is a Model that represents Statistical Data that can be shown different ways: a Pie chart, a Bar chart etc. In this example the Statistical Data Model is a Domain Model.
In the example above, the Model will probably be shared between the two View-Presenter pairs , The PieChart and the BarChart. If you use the Observer pattern, when one of the View-Presenter pairs update the StatisticalModel, it will raise changed events, and both View-Presenter pairs will receive notifications for this change and update.
Sometimes an application needs an ApplicationModel. This model can be shared between different View-Presentation pairs. Let's take a look at a verfy simplified example.
Let's say we have a File Browser application like Windows Explorer. This GUI of the application has two major parts: The left panel that shows a Tree of the folders and the middle File-Folder panel. When a folder is selected in the left folders tree panel, files and folders from the selected folder must be shown in the middle panel. We can do this by defining an ApplicationModel that will capture and represent the above logic and be shared between both View-Presentation pairs for the left and middle panels.
Note: I'll omit details to simply the example and write less code
public class ApplicationState {
// singleton, it's evil I know,
// but it's the simplest way without DI or ServiceLocator
private static ApplicationState mInstance = new ApplicationState();
public static ApplicationState getInstance() { return mInstance; }
private Folder mSelectedFolder;
public bool hasSelectedFolder() { return mSelectedFolder != null; }
public Folder getSelectedFolder() { return mSelectedFolder; }
public Folder setSelectedFolder(Folder f) {
mSelectedFolder = f;
RaiseSelectedFolderChangedEvent();
}
// method for registering listeners, raising events etc.
}
public class FoldersTreeViewPresenter {
private ApplicationState mApplicationState;
public void onSelectFolder(FolderView view) {
// select the folder in the view
mApplicationState.setSelectedFolder(view.Folder);
}
}
public class FilesFoldersViewPresenter : ApplicationStateListener {
private ApplicationState mApplicationState;
public FilesFoldersViewPresenter() {
// you can use service locator, dependency injection, whatever
mApplicationState = ApplicationState.getInstance();
mApplicationState.addEventListener(this);
}
private void getFilesAndFoldersFromFileSystem(Folder folder) {
// get from fs
// fill views with them etc.
}
private void clearView() {
// clear the panel
}
public void onApplicationStateChanged() {
if(mApplicationState.hasSelectedFolder()){
getFilesAndFoldersFromFileSystem(mApplicationState.getSelectedFolder());
}
else {
clearView();
}
}
}
In this example we created a shared object that represent the application state and the logic, that our application has a selection that can be changed. In this case the ApplicationState class is part of the Model and is an Application Model. Because it is shared and it's life time is the same as the application (it exists as long as the application is running) it will hold the state. Views and Presenters are created and destroyed, but this class will exist and hold the state, so that when a new View and/or Presenter is created it can check this state and do something.
In my experince people do concentrate on Views and Presenters more, while they should work on their Models. Peronally I use Models alot as it makes things cleaner and the application easier to understand.
Of course, using Models doesn't always work, so when they don't you can use messaging, having one Presenter sending messages to others. Here's an example with the same File Browser app.
public class MessageBus {
// static this time, you can use DI or ServiceLocator with interface
public static void sendMessage(object m) { }
public static void registerListener(MessageListener listener) { }
}
public class FoldersTreeViewPresenter {
public void onSelectFolder(FolderView view) {
// select the folder in the view
MessageBus.sendMessage(new FolderSelected(view.Folder));
}
}
public class FilesFoldersViewPresenter : MessageListener {
public FilesFoldersViewPresenter() {
MessageBus.addListener(this);
}
private void getFilesAndFoldersFromFileSystem(Folder folder) {
// get from fs
// fill views with them etc.
}
public void onMessage(object m) {
if(m instanceof FolderSelected) {
FolderSelected folderSelectedMessage = (FolderSelected)m;
getFilesAndFoldersFromFileSystem(folderSelectedMessage.Folder);
}
}
}
Depending on your specific case, if you can create a nice Model, either a Domain, Application or Presentation, do it. Share this Model thus creating a dependency on the Model from the Presenters instead of creating a dependency between Presenters. This way you have loose coupling between Presenters and you can change them much easier
If you can't use a Model, use a Messages. It's a nice way to decouple Presenters by creating a protocol of messages that are used for communication.
Check this article on using messages for collaboration between components.
Also here are some good articles on GUI architectures:
https://martinfowler.com/eaaDev/uiArchs.html
http://aspiringcraftsman.com/2007/08/25/interactive-application-architecture/
I understand that ViewModel in the Architecture component is for storage and managing data so it will not be lost during config changes.
For example, my activity has nothing do with LiveData or using storage Data. Should I still go through ViewModel? or directly instantiate the Repo Class and call the insertion method? I hope that make sense
An Example of my usage of ViewModel
public class MainViewModel extends AndroidViewModel {
private DataRepo dataRepo;
private LiveData<List<Group>> groupList;
private LiveData<List<Bill>> billList;
public MainViewModel(Application application) {
super(application);
dataRepo = new DataRepo(this.getApplication));
groupList = dataRepo.getGroup();
billList = dataRepo.getBill();
}
public LiveData<List<Group>> getGroupList() {
return groupList:
}
public LiveData<List<Bill>> getBillList() {
return billList:
}
public void insertGroupAndMember(Group group) {
dataRepo.insertGroupAndMember(group);
}
public void insertBills(List<Bill> bills) {
dataRepo.insertBills(bills);
}
public List<Member> getMemberList(Group group) {
return dataRepo.getMembers(group);
}
}
I think you want to use a ViewModel to keep your UI controller as clean as possible. Your viewmodel should call the repo to do simple CRUD operations.
See below snippet from documentation:
Requiring UI controllers
to also be responsible for loading data from a database or network
adds bloat to the class. Assigning excessive responsibility to UI
controllers can result in a single class that tries to handle all of
an app's work by itself, instead of delegating work to other classes.
Assigning excessive responsibility to the UI controllers in this way
also makes testing a lot harder.
Here are some points I would advice you to consider:
MVVM as a pattern has it's roots back in 2000-th, for example, here is Martin Fowler's article about the concept, and in 2005 John Gossman announced the pattern in his blog. Yes, it solves the problem with rotation in android's implementation of the pattern, but this problem could be solved without it. MVVM is actualy needen for separation of presentation state from views that are seen to the end user. As Wiki says -
The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder, which automates communication between the view and its bound properties in the view model. The view model has been described as a state of the data in the model.
So, primarily it is (like all other GUI architectural patterns in their root) about abstraction between view and domain parts of the application, so that they can vary independently and subsequent changes to the system will be cheap.
Instantiating domain objects in the view scope and their subsequent use by the view leads to tight coupling between the view and domain objects, which is a bad characteristic of any system. Also, it is one more reason to change view's internals, because if construction logic of the domain object changes - view will have to be changed too.
If ViewModel is exessive for you (as I can see, its benefits are not relevant for you in this particular case, because the UI is not very complex and it's state is lightweight), consider using a less heavy-weight abstraction, such as MVP. Thus, you will be able to preserve abstraction between view and model in your application (no unwanted coupling) and you won't have to support the code that you don't benefit from.
I'm adopting MVVM to my Android apps recently. In order to solve the problems underlying with the lifecycle of an app, Google had released LiveData.
The usage of LiveData has different scenarios, as pointed out in the medium article wrote by Jose Alcérreca, you can use SingleLiveEvent or something like the event wrapper pattern.
I want to make sure the SingleLiveEvent, or the event wrapper pattern, which one would be the best practice to use with LiveData in Android MVVM architecture. And I found the Google I/O app of this year(2018) have no usages of SingleLiveEvent, it uses event wrapper pattern instead.
Previously I have opened an issue on the project android-architecture, at first I'm seeking an official reply, but it seems to have no comments at all. As a result, I would like to hear the advice from the developers who already use these stuff and have reflections on it.
Please share your precious experiences, thank you in advance.
I'm not a fan of SingleLiveEvent because it restricted to one observer but you can add many observers as well, so it can be error-prone.
But in a very simple scenario(like the todo app that you mentioned), it can be a better option than event wrapper pattern.
In a complex scenario, event wrapper pattern would be a better option, but it also has some limitations. This implementation assumes you only have one main consumer (see getContentIfNotHandled). So, I think dealing with multiple observers will cause boilerplate to decide which one is the main consumer or when I should call getContentIfNotHandled or peekContent.
But, All these limitations can be fixed with your own implementation.
For example here is an extended version of SingleLiveEvent that supports multiple observers:
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private LiveData<T> liveDataToObserve;
private final AtomicBoolean mPending = new AtomicBoolean(false);
public SingleLiveEvent() {
final MediatorLiveData<T> outputLiveData = new MediatorLiveData<>();
outputLiveData.addSource(this, currentValue -> {
outputLiveData.setValue(currentValue);
mPending.set(false);
});
liveDataToObserve = outputLiveData;
}
#MainThread
public void observe(#NonNull LifecycleOwner owner, #NonNull Observer<T> observer) {
liveDataToObserve.observe(owner, t -> {
if(mPending.get()) {
observer.onChanged(t);
}
});
}
#MainThread
public void setValue(T value) {
mPending.set(true);
super.setValue(value);
}
}
As you see, It's not about SingleLiveEvent vs event wrapper pattern, It all depends. Personally, I use other patterns (like patterns existing in React/Flux world) for dealing with states.
Keep in mind that there is no silver bullet in software engineering.
SingleLiveData is restricted to one observer, EventLiveData described in this article supports multiple observers.
You use it just like regular live data. No hacking or adding unnecessary complexity to code.
implementation 'com.rugovit.eventlivedata:eventlivedata:1.0'
MutableEventLiveData<String> eventLiveData =new MutableEventLiveData<>();
viewModel.event.observe(this, Observer {
// ...
})
It is extension of livedata and supports every feature of livedata.
Unlike other solutions this supports multiple observers.
Github link: https://github.com/rugovit/EventLiveData
I have a BIG Android app that needs to run different code for depending on the OS version, the manufacturer, and many other things. This app however needs to be a single APK. It needs to be smart enough at runtime to determine which code to use. Until now we have been using Guice but performance issues are causing us to consider migrating to Dagger. However, I've been unable to determine if we can achieve the same use case.
The main goal is for us have some code that runs at startup to provide a list of compatible Modules. Then pass that this list to Dagger to wire everything up.
Here is some pseudocode of the current implementation in Guice we want to migrate
import com.google.inject.AbstractModule;
#Feature("Wifi")
public class WifiDefaultModule extends AbstractModule {
#Override
protected void configure() {
bind(WifiManager.class).to(WifiDefaultManager.class);
bind(WifiProcessor.class).to(WifiDefaultProcessor.class);
}
}
#Feature("Wifi")
#CompatibleWithMinOS(OS > 4.4)
class Wifi44Module extends WifiDefaultModule {
#Override
protected void configure() {
bind(WifiManager.class).to(Wifi44Manager.class);
bindProcessor();
}
#Override
protected void bindProcessor() {
(WifiProcessor.class).to(Wifi44Processor.class);
}
}
#Feature("Wifi")
#CompatibleWithMinOS(OS > 4.4)
#CompatibleWithManufacturer("samsung")
class WifiSamsung44Module extends Wifi44Module {
#Override
protected void bindProcessor() {
bind(WifiProcessor.class).to(SamsungWifiProcessor.class);
}
#Feature("NFC")
public class NfcDefaultModule extends AbstractModule {
#Override
protected void configure() {
bind(NfcManager.class).to(NfcDefaultManager.class);
}
}
#Feature("NFC")
#CompatibleWithMinOS(OS > 6.0)
class Nfc60Module extends NfcDefaultModule {
#Override
protected void configure() {
bind(NfcManager.class).to(Nfc60Manager.class);
}
}
public interface WifiManager {
//bunch of methods to implement
}
public interface WifiProcessor {
//bunch of methods to implement
}
public interface NfcManager {
//bunch of methods to implement
}
public class SuperModule extends AbstractModule {
private final List<Module> chosenModules = new ArrayList<Module>();
public void addModules(List<Module> features) {
chosenModules.addAll(features);
}
#Override
protected void configure() {
for (Module feature: chosenModules) {
feature.configure(binder())
}
}
}
so at startup the app does this:
SuperModule superModule = new SuperModule();
superModule.addModules(crazyBusinessLogic());
Injector injector = Guice.createInjector(Stage.PRODUCTION, superModule);
where crazyBusinessLogic() reads the annotations of all the modules and determines a single one to use for each feature based on device properties. For example:
a Samsung device with OS = 5.0 will have crazyBusinessLogic() return the list { new WifiSamsung44Module(), new NfcDefaultModule() }
a Samsung device with OS = 7.0 will have crazyBusinessLogic() return the list { new WifiSamsung44Module(), new Nfc60Module() }
a Nexus device with OS = 7.0 will have crazyBusinessLogic() return the list { new Wifi44Module(), new Nfc60Module() }
and so on....
Is there any way to do the same with Dagger? Dagger seems to require you to pass the list of modules in the Component annotation.
I read a blog that seems to work on a small demo, but it seems clunky and the extra if statement and extra interfaces for components might cause my code to balloon.
https://blog.davidmedenjak.com/android/2017/04/28/dagger-providing-different-implementations.html
Is there any way to just use a list of modules returned from a function like we are doing in Guice? If not, what would be the closest way that would minimize rewriting the annotations and the crazyBusinessLogic() method?
Dagger generates code at compile-time, so you are not going to have as much module flexibility as you did in Guice; instead of Guice being able to reflectively discover #Provides methods and run a reflective configure() method, Dagger is going to need to know how to create every implementation it may need at runtime, and it's going to need to know that at compile time. Consequently, there's no way to pass an arbitrary array of Modules and have Dagger correctly wire your graph; it defeats the compile-time checking and performance that Dagger was written to provide.
That said, you seem to be okay with a single APK containing all possible implementations, so the only matter is selecting between them at runtime. This is very possible in Dagger, and will probably fall into one of four solutions: David's component-dependencies-based solution, Module subclasses, stateful module instances, or #BindsInstance-based redirection.
Component dependencies
As in David's blog you linked, you can define an interface with a set of bindings that you need to pass in, and then supply those bindings through an implementation of that interface passed into the builder. Though the structure of the interface makes this well-designed to pass Dagger #Component implementations into other Dagger #Component implementations, the interface may be implemented by anything.
However, I'm not sure this solution suits you well: This structure is also best for inheriting freestanding implementations, rather than in your case where your various WifiManager implementations all have dependencies that your graph needs to satisfy. You might be drawn to this type of solution if you need to support a "plugin" architecture, or if your Dagger graph is so huge that a single graph shouldn't contain all of the classes in your app, but unless you have those constraints you may find this solution verbose and restrictive.
Module subclasses
Dagger allows for non-final modules, and allows for the passing of instances into modules, so you can simulate the approach you have by passing subclasses of your modules into the Builder of your Component. Because the ability to substitute/override implementations is frequently associated with testing, this is described on the Dagger 2 Testing page under the heading "Option 1: Override bindings by subclassing modules (don’t do this!)"—it clearly describes the caveats of this approach, notably that the virtual method call will be slower than a static #Provides method, and that any overridden #Provides methods will necessarily need to take all parameters that any implementation uses.
// Your base Module
#Module public class WifiModule {
#Provides WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
/* abstract would be better, but abstract methods usually power
* #Binds, #BindsOptionalOf, and other declarative methods, so
* Dagger doesn't allow abstract #Provides methods. */
throw new UnsupportedOperationException();
}
}
// Your Samsung Wifi module
#Module public class SamsungWifiModule {
#Override WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
return new SamsungWifiManager(dep1); // Dep2 unused
}
}
// Your Huawei Wifi module
#Module public class HuaweiWifiModule {
#Override WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
return new HuaweiWifiManager(dep1, dep2);
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
.baseWifiModule(new SamsungWifiModule()) // or name it anything
// via #Component.Builder
.build();
This works, as you can supply a single Module instance and treat it as an abstract factory pattern, but by calling new unnecessarily, you're not using Dagger to its full potential. Furthermore, the need to maintain a full list of all possible dependencies may make this more trouble than it's worth, especially given that you want all dependencies to ship in the same APK. (This might be a lighter-weight alternative if you need certain kinds of plugin architecture, or you want to avoid shipping an implementation entirely based on compile-time flags or conditions.)
Module instances
The ability to supply a possibly-virtual Module was really meant more for passing module instances with constructor arguments, which you could then use for choosing between implementations.
// Your NFC module
#Module public class NfcModule {
private final boolean useNfc60;
public NfcModule(boolean useNfc60) { this.useNfc60 = useNfc60; }
#Override NfcManager provideNfcManager() {
if (useNfc60) {
return new Nfc60Manager();
}
return new NfcDefaultManager();
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
.nfcModule(new NfcModule(true)) // again, customize with #Component.Builder
.build();
Again, this doesn't use Dagger to its fullest potential; you can do that by manually delegating to the right Provider you want.
// Your NFC module
#Module public class NfcModule {
private final boolean useNfc60;
public NfcModule(boolean useNfc60) { this.useNfc60 = useNfc60; }
#Override NfcManager provideNfcManager(
Provider<Nfc60Manager> nfc60Provider,
Provider<NfcDefaultManager> nfcDefaultProvider) {
if (useNfc60) {
return nfc60Provider.get();
}
return nfcDefaultProvider.get();
}
}
Better! Now you don't create any instances unless you need them, and Nfc60Manager and NfcDefaultManager can take arbitrary parameters that Dagger supplies. This leads to the fourth solution:
Inject the configuration
// Your NFC module
#Module public abstract class NfcModule {
#Provides static NfcManager provideNfcManager(
YourConfiguration yourConfiguration,
Provider<Nfc60Manager> nfc60Provider,
Provider<NfcDefaultManager> nfcDefaultProvider) {
if (yourConfiguration.useNfc60()) {
return nfc60Provider.get();
}
return nfcDefaultProvider.get();
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
// Use #Component.Builder and #BindsInstance to make this easy
.yourConfiguration(getConfigFromBusinessLogic())
.build();
This way you can encapsulate your business logic in your own configuration object, let Dagger provide your required methods, and go back to abstract modules with static #Provides for the best performance. Furthermore, you don't need to use Dagger #Module instances for your API, which hides implementation details and makes it easier to move away from Dagger later if your needs change. For your case, I recommend this solution; it'll take some restructuring, but I think you'll wind up with a clearer structure.
Side note about Guice Module#configure(Binder)
It's not idiomatic to call feature.configure(binder()); please use install(feature); instead. This allows Guice to better describe where errors occur in your code, discover #Provides methods in your Modules, and to de-duplicate your module instances in case a module is installed more than once.
Is there any way to just use a list of modules returned from a
function like we are doing in Guice? If not, what would be the closest
way that would minimize rewriting the annotations and the
crazyBusinessLogic() method?
Not sure this is the answer you're looking for, but just in case you do have other options and for other community members I will describe completely different approach.
I would say that the way you used Guice until now is an abuse of DI framework, and you will be much better off leveraging this opportunity to remove this abuse instead of implementing it in Dagger.
Let me explain.
The main goal of dependency injection architectural pattern is to have construction logic segregated from functional logic.
What you basically want to achieve is standard polymorphism - provide different implementations based on a set of parameters.
If you use Modules and Components for that purpose, you will end up structuring your DI code according to business rules governing the need for these polymorphic implementations.
Not only will this approach requires much more boilerplate, but it also prevents emergence of cohesive Modules that have meaningful structure and provide insights into application's design and architecture.
In addition, I doubt you will be able to unit test these business rules "encoded" inside dependency injection logic.
There are two approaches which are much better IMHO.
First approach is still not very clean, but, at least, it doesn't compromise the large scale structure of dependency injection code:
#Provides
WifiManager wifiManager(DeviceInfoProvider deviceInfoProvider) {
if (deviceInfoProvider.isPostKitKat() ) {
if (deviceInfoProvider.isSamsung()) {
return new WifiMinagerSamsungPostKitKat();
} else {
return new WifiMinagerPostKitKat();
}
} else {
return new WifiMinagerPreKitKat();
}
}
The logic that chooses between implementation still resides in DI code, but, at least, it did not make it into the large scale structure of that part.
But the best solution in this case is to make a proper object oriented design, instead of abusing DI framework.
I'm pretty sure that the source code of all these classes is very similar. They might even inherit from one another while overriding just one single method.
In this case, the right approach is not duplication/inheritance, but composition using Strategy design pattern.
You would extract the "strategy" part into a standalone hierarchy of classes, and define a factory class that constructs them based on system's parameters. Then, you could do it like this:
#Provides
WiFiStrategyFactory wiFiStrategyFactory(DeviceInfoProvider deviceInfoProvider) {
return new WiFiStrategyFactory(deviceInfoProvider);
}
#Provides
WifiManager wifiManager(WiFiStrategyFactory wiFiStrategyFactory) {
return new WifiMinager(WiFiStrategyFactory.newWiFiStrategy());
}
Now construction logic is simple and clear. The differentiation between strategies encapsulated inside WiFiStrategyFactory and can be unit tested.
The best part of this proper approach is that when a new strategy will need to be implemented (because we all know that Android fragmentation is unpredictable), you won't need to implement new Modules and Components, or make any changes to DI structure. This new requirement will be handled by just providing yet another implementation of the strategy and adding the instantiation logic to the factory.
All that while being kept safe with unit tests.
I try to understand what the best way is to program a "clean" Android app. I found an interesting article about it where they use a kind of a 3 layer architecture.
Now I read that android uses the MVP design pattern and try to understand this. The way I understand the MVP principle (in the android context) is that:
the Model layer are the logic classes
the presenter are the classes that are "linked" to an XML (the activities)
the passive view are the XML's.
Is this correct?
When this is correct, is it then also correct that the 3 layer model fits perfectly in the MVP principle because:
the presentation layer from the 3 layer architecture fits in the presenter layer of MVP
The business and the data layer from the 3 layer architecture fits perfectly in the model part of the MVP?
I hope my questions are clear because it is a complicated topic for me.
Maybe this clears up my vision (way of thinking) about this...
first thing I wanted to clarify is that MVP or any other pattern for that matter is no specific of Android dev and, can be applied to any other framework.
I think you got the gist of it:
view is usually implemented by activities and fragments and will contain the reference to the presenter
the presenter is that middle man between the view and model. Retrieves data from the model and returns it already formatted to the view so it doesn't need to do anything else but display it.
the model can be seen in a simplistic way as the "data provider". It can be as complex as you want, using internal db, lots of clases etc.
If you are interested in Android apps architecture I suggest you watch this talk given at Android dev summit this year. It is one of the bests I've seen
https://www.youtube.com/watch?v=BlkJzgjzL0c
Even though this question has an answer, I don't think this answer is complete by any means.
MVP is a general concept which can have many various implementations, some of which differ substantially. Moreover, the concept itself is very ambiguous - different people can have different concepts in mind when they say MVP. One of the most widespread ones is shown in the below picture:
Regardless of implementation, the general definitions of MVP components are:
Model: abstraction of "application state storage". The definition of what the "state" is and how it is stored are implementation details. Model implementations should not have dependency on View or Presenter.
View: abstraction of "user interface". The definition of who the "user" is and how it interacts with the View are implementation details. View implementations should not have dependency on Model or Presenter.
Presenter: encapsulates application's business logic. Presenter processes user input events received from view, and alters application's state stored in model in response. Presenter also processes changes of application's state stored in model and updates view in response. Presenter usually depends on both the View and the Model.
If you need more information about MVP in context of Android development, you can find it in this post: MVP and MVC Architectural Patterns in Android
Important issues which need to be addressed while implementing MVP in android are activity leaks which cause memory leaks and app crashes due to background process updating closed activity.
Due to presenter having reference to activity, if presenter can't be garbage collected, activity will stay in memory.
Both of the issues can be solved by using life cycle methods of activity or fragment and releasing resources in those methods so that memory leaks and app crashes are prevented.
Cleaning up of resources related background work can be easily implemented using RXJava, for more information about MVP and MVP with RXJava, see http://www.zoftino.com/android-model-view-presenter-mvp-pattern-example
Here is simplest way to implement MVP pattern in your application android_mvp_login_sample
As you have come to know basics of Clean Architechure. The following example depicts how actual your MVP pattern is implemented.
Example:
interface BaseContract {
interface BaseView {
//Methods for View
void onDoSomething();
}
interface BasePresenter {
void doSomething();
}
}
class BaseMainPresenter implements BaseContract.BasePresenter {
BaseContract.BaseView view;
BaseMainPresenter(BaseContract.BaseView view) {
this.view = view;
}
#Override
public void doSomething() {
if (view != null)
view.onDoSomething();
}
}
class DemoClass implements BaseContract.BaseView {
//Create object of Presenter
/****
* Example :
* BaseMainPresenter baseMainPresenter = new BaseMainPresenter(this);
*/
#Override
public void onDoSomething() {
//Deal with Context here.
}
}
Refer below link for sample Actual implementation with scenario & learn more about Clean Architechure : https://github.com/android10/Android-CleanArchitecture
Here on github
https://github.com/saksham24/Android-Firebase-Mvp-Mvc-Mvvm-chat
i made a repo containing 3 applications with same functionality but written in 3 different android patterns(Mvc, Mvp, Mvvm)
Understanding three different pattern is quite easy if we get a simple good example on them so i made a repo to contribute my knowledge to this developer community.
Also the repository is written using proper java guidelines and conventions(including naming and packages, modules) so people looking for such project can also view this repository.
now
if you want to know the difference between android Mvp,Mvc, MvvM see this explanation by realm
https://academy.realm.io/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/
if you want to compare three pattern see this wonder full blog https://thinkmobiles.com/blog/mvp-vs-mvvm-android-patterns/
Now I read that android uses the MVP design pattern and try to
understand this. The way I understand the MVP principle (in the
android context) is that:
the Model layer are the logic classes
the presenter are the classes that are "linked" to an XML (the activities)
the passive view are the
XML's.
Is this correct?
Not fully: for the Model layer it is true, but for the Presenter it is not. The Presenter is not linked to XML although it has reference to the View through its constructor. The View is the Activity/Fragment in android.
You might want to check here for a sample MVP app for android.