Can I use two viewmodel for one fragment? - android

I am using MVVM in my Android project. I have Create and Edit fragments. This 2 fragments have largely the same function. If I write functions which they have the same function in a common view model, Can I use the common viewmodel with own viewmodel of fragments. For example Can I use like below;
CommonViewModel(){
void selectPriority()
.
.
.
otherthings...}
CreateViewModel(){
LiveData<CommonViewModel> cvm;
.
.
.
otherthings...}
EditViewModel(){
LiveData<CommonViewModel> cvm;
.
.
.
otherthings...}
Instead of this
CreateViewModel(){
void selectPriority()
.
.
.
otherthings...}
EditViewModel(){
void selectPriority()
.
.
.
otherthings...}
Or can you suggest to me different way which I can use?

You can do this through Inheritance,Make a common view model and extend it in edit and creat view model, like
class CreatEditViewModel{
public void selectPriority(){
//to something....
}
public void other(){
//to something....
}
}
class CreateViewModel extends CreatEditViewModel{
}
class EditViewModel extends CreatEditViewModel{
}
You can not put these logic in BaseViewModel because BaseViewModel is extended by all ViewModel.

You can with the help of Inheritance, create a base class and put all the common functionality there, then create two more classes which inherit the base class. this way you can achieve what you want.
e.g.
class BaseViewModel{
public void selectPriority(){
}
public void other(){
}
}
class CreateViewModel extends BaseViewModel{
}
class EditViewModel extends BaseViewModel{
}
With the above example, CreateViewModel and EditViewModel both inherit BaseViewModel hence they have access to all the functions of BaseViewModel class. All the common methods will be available wit BaseViewModel. The methods you would create in CreateViewModel and EditViewModel will not be visible to each other.

Related

Should I create BaseActivity/Presenter and View in Mosby MvP concept?

I'm trying to understand concept of MvP design pattern. I mean, I get it, its quite easy. The main problem is optimal implementation. I tried to make my own BaseActivity, BasePresenter and BaseView just to extract part of a joint from all of my activities, I've done this this way:
BaseActivity
public abstract class BaseActivity<T extends BasePresenter<? extends IBaseView>> extends FragmentActivity implements IBaseView {
protected T presenter;
private ActivityConfig activityConfig;
#Override
final protected void onCreate(Bundle savedInstanceState) {
activityConfig = getConfig();
super.onCreate(savedInstanceState);
presenter = createPresenter();
setContentView();
initLibraries();
prepareView(savedInstanceState);
addFragments();
}
protected abstract ActivityConfig getConfig();
protected abstract T createPresenter();
protected abstract void prepareView(Bundle savedInstanceState);
protected abstract void addFragments();
private void setContentView(){
View root = View.inflate(this, activityConfig.layoutId, null);
setContentView(root);
}
private void initLibraries() {
ButterKnife.bind(this);
Timber.plant(new Timber.DebugTree());
}
#Override
public BaseActivity getCurrentContext() {
return this;
}
#Override
public T getPresenter() {
return presenter;
}
}
BasePresenter
public abstract class BasePresenter<T extends IBaseView> {
public abstract void loadData(boolean refresh);
}
BaseView
public interface IBaseView {
BaseActivity getCurrentContext();
BasePresenter getPresenter();
}
It works fine but I feel like this is bad designed so I want to use Mosby instead. The problem is that all of the tutorials don't touch aspect of base classes, they just use Mosby's ones as base (with is bad I suppose? couse I have to duplicate my code (Butterknife.bind() for example). So can you guys give me some good designed quickstart classes for Mosby MVP or give me some tips how should I divide my project? Thanks!
So I see two possibilities:
You could extend from Mosby's MvpActivity as your base class and add your staff like initView(), initLibraries() etc. So that BaseActivity<P extends BasePresenter<? extends BaseView>> extends MvpActivity<P> implements BaseView. Then MyFooActivity extends BaseActivity<FooPresenter>. So you include Butterknife once in BaseActivity and it should work. However, you might have to duplicate that code like Butterknife.bind()` for Fragments, as Activity and Fragments obviously don't have the same super class. I will show you how to solve that above.
Do the other way around: Integrate Mosby's functionality into your BaseActivity. Mosby is build with the principle of "favor composition over inheritance". So what does this actually mean? Mosby offers a ActivityMvpDelegate. As the name already suggests this delegate does all the work of instantiating Presenter etc. But instead of inheriting from MvpActivity you use this delegate and invoke the corresponding delegate methods. Actually Mosby's MvpActivity is doing exactly that if you have a look at the source code. So instead of extending from Mosby'sMvpActivity you simply use MvpActivityDelegate in your BaseActivity.
So what about duplicating code like Butterknife.bind() i.e. in Activity and Fragment. Well, Mosby can share his code like instantiating Presenter etc. between Activity and Fragment because both use the mosby delegate.
So you could apply the same principle: You could put the shared code into a delegate and call the delegate from both, activity and fragments.
The question is: is it worth i.e. Butterknife.bind() is just one single call. You would also have to make one single call yourDelegate.doSomething() ...
But if you have to reuse "critical code" between activity and fragments then favor composition like Mosby does.
If you know that you are only working with Activites then extending from Mosby's MvpActivity would also be a good option as described in 1. solution.
I just wanted to add to sockeqwe's first answer.
It is perfectly fine to create your own base class where it makes sense. It's also pretty straightforward.
For example, I needed to create a base Fragment with some default behavior. All you need to do is duplicate the base generic type signature and pass it along to the base class.
For example:
public abstract class MyBaseFragment<V extends MvpView, P extends MvpPresenter<V>> extends MvpFragment<V, P>

Android, where to put my own Bluetooth class

Well, I'm at a dilemma here. I made my own class that uses the Bluetooth class from android but I'm not sure where to put it. Extending the android Bluetooth class seems like a good idea but I need to override the onActivityResult() which is only available to an activity class. So, where would I put my class so that I have access to onActivityResult() (keeping in mind the idea here is to use as few dependencies as possible)?
In other words, I want to move the Bluetooth code from the main activity to a separate class.
You should to use separate file for each class. You can create a folder "engine". For example: com.mycorp.myapp.engine. You can get access to onActivityResult() very simple. For example: MainActivity.onActivityResult(). Note: function should be public.
Or you can pass your activity to your CustomBluetooth's constructor.
public class CustomBluetooth {
private Activity mActivity;
/* Constructor */
public CustomBluetooth (Activity pActivity ) {
super();
this.mActivity = pActivity;
}
/* Your functions */
public int getResult() {
return this.mActivity.onActivityResult();
}
}
Alex. P.S. Sorry for my English:)
Add an interface to your Bluetooth class and implement the interface in your activity.

Using RoboGuice to inject Classes in my activity

I am new to using roboguice and i am having a hard time configuring injection in my application.
Say that i have the following interface
public interface IAPICall{
void doSomething();
}
and i have two different implementations of my interface
public class MyApiCall implements IAPICall{
public void doSomething(){
}
}
public class MyMockApicall implements IAPICall{
public void doSomething(){
}
}
Now my requirement is that i want to inject the interface into my activity. How do i configure which concrete class gets injected. During testing i want to inject my mock class while during production i want to inject the actual class. How can i configure this ?
Kind Regards
In your guice configuration module :
public class GuiceConfigurationModule extends AbstractModule {
...
#Override
protected void configure() {
...
bind(IAPICall.class).to(MyApiCall.class);
...
}
...
}
In your activity :
#Inject
IAPICall someApiCall;
The best way to play with a mocked interface during test is to create a test module where the binding are pointing to mockup classes. There is a tutorial on Robolectric
on how to do that.
http://pivotal.github.com/robolectric/roboguice.html
To add your module to your application, add a roboguice.xml file in the values ressources folder :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="roboguice_modules">
<item>com.stackoverflow.test.GuiceConfigurationModule</item>
</string-array>
</resources>
This is described here :
http://code.google.com/p/roboguice/wiki/UpgradingTo20

Common Code for Activity and PreferenceActivity

I'm using common code in my Activity like this:
abstract class CommonCode extends Activity {
//Common Code here...
}
then in my "Activity" I extend CommonCode instead of Activity and it all works fine.
My problem arise when I try to use commoncode in a PreferenceActivity, I tried:
abstract class CommonCode extends Activity {
class CommonCodePreferences extends PreferenceActivity {
}
//Common Code here...
}
but it isn't right.
How can I do it?
May I suggest that you prefer composition over inheritance and do something like this:
abstract class CommonCode {
Activity parent;
public CommonCode(Activity activity) {
parent = activity;
}
}
class MyActivity extends Activity {
CommonCode commonCode;
public MyActivity() {
commonCode = new CommonCode(this);
}
}
This is a little more code to write in each activity, but it has a lot of advantages:
It can also easily handle PreferenceActivity and other classes
It is easier to test and mock
I usually have one each since you can't mess with the existing hierarchy of the base classes.
For example, I have an ActivityBase, ServiceBase, ListActivityBase, etc. If you want to have common code that they all use, I would suggest using composition - each of your base classes has a single instance of your CommonCode class or something to that effect. Another possibility is to use static methods and/or use a custom Application class (requires declaring the custom Application class in the manifest in the name attribute of the application element)

How to override a class within an Android library project?

The following is my situation:
I have a library project and a project based on it. Now in the library I have two classes A and B, whereby A uses B. In the project using the library, I have another class B, which should override the class B from the library.
But every time class A makes a call, it ends up in the class B from the library.
How can I tell Android that class B from my project should be used INSTEAD of class B from the library?
That does not work with the current layout. You have to use the strategy pattern. In your library define LibA with a constructor that takes a object of type LibB in the constructor:
class LibA{
LibB b;
public LibA(LibB b)
this.b = b;
}
}
Then you can override LibB in your project and create LibA with the class that extends LibB:
class ProjectB extends LibB{
}
LibA a = new LibA(new ProjectB());
Answer to Turbos question:
You want to start Project-Activities from your Library. So then move the code that creates the Intent into your Projects, because only in your project you know the type or name of the Activity to be started.
The solution you mentioned in your comment (here) creates the Intent in the library project, by guessing the name of the Activity that should be started. There is nothing really wrong with that but it's not an elegant solution. You can only start Activities that follow that special naming scheme. And because of that you cannot start arbitrary Activities that are visible in your projects like Activities from other libraries, where you cannot change the name of the class.
To move the Intent creation into your libraries you can i.e. use the strategy, template or factory-method pattern. See Design Patterns on Wikipedia for even more (creational) patterns that match your library design.
A simple solution would be:
Create an abstract LibraryActivity and extend your ProjectActivities from it. The LibraryActivity defines an abstract method that returns the Intent. The implementation of that abstract method is done in your ProjectActivities.
abstract class LibActivity{
private void doSomething(){
//Library does something
//and finally calls createIntent() to start an project specific Activity
startActivity(this.createIntent());
}
protected abstract Intent createIntent();
}
class ProjectActivity extends LibActivity{
protected Intent createIntent(){
return new Intent(ProjectActivity.this, AnyActivityYouWant.class);
}
}
I dont know if this is the best way to do it but i do it this way;
I create a class A from the project and this class extends form the library project
public class A extends libraryProject_A{
//here i put all methods from the new class B to override methods from library class B
}
As I see from your comment you have class A that uses class B
But class B should be different according to which project you're using.
I think you need to create a base class say BaseB that will be an instance variable in class A, and you might have a setter and getter for this Or you can make it a parameter passed to the constructor of class A. and when instantiating A you should choose which one to use.
Let's have a look at code
Class A {
private BaseB b;
public A(BaseB aB) {
b = aB;
}
public void set(BaseB aB) {
b = aB;
}
public BaseB get() {
return b;
}
}
interface BaseB {
}
// in the library have this
class B implements BaseB {
}
// in your project have the other implementation
class B implements BaseB {
}
// you can then instantiate A like this
A a = new A(new B());
// you can choose which one to use here in the previous statement.

Categories

Resources