I was looking at the google samples for MVP and I saw this as the last statement in onCreate of the activity:
new TaskDetailPresenter(
taskId,
Injection.provideTasksRepository(getApplicationContext()),
taskDetailFragment);
This code seems weird to me.
It instantiates an object (TaskDetailPresenter) that is local and not assigned anywhere and in it associates the fragment with the presenter.
Classes defined here
Is this really how it is supposed to be done? Because it seems not a good practice to me
In TaskDetailPresenter constructor they have:
mTaskDetailView.setPresenter(this);
So the presenter object is passed to the fragment ("View" in MVP). And that fragment stores a reference to the presenter. This is ok - View can easily communicate with its presenter with this configuration.
But the trick they use here - calling setPresenter(this) before the constructor finishes is a bad thing. Here you can find an explanation of this problem: http://www.javapractices.com/topic/TopicAction.do?Id=252
It may be ok if that reference is just saved to a property and everything happens in one thread. But something may change in the future and we can get into trouble.
Related
In Android, whenever we want to have a View like a custom Button subclass call out to a consumer that's using it in a layout, the normal pattern that I've seen used is to define a Listener interface, define methods on the interface that are to be implemented, and then have a listener property in the custom View subclass that will call them at appropriate times. This works well enough but sometimes I feel that this can get unwieldy and less direct, at times - especially when I just want a single method and I know there's not going to be a future addition.
I've been switching to Kotlin recently and I've been wondering if it makes sense to simply have a direct function var declared in the View subclass, as Optional with a null default value, something like this:
class SuperAmazingButton: ImageButton{
var customAction: (()->Unit)? = null
}
When we need to call customAction we can do it in a simple one liner like this along with the safe null check:
customAction?.invoke()
What I'd like to know is if there are any downsides to this approach? Will the android Context that is holding on to the View somehow get leaked when the Activity or Fragment gets dismissed? Are there any other problems that can occur? I mean this looks so simple, easy and straightforward without requiring any new files - it's almost too good to be true!
Context is used on several place such as in activity. But why we use context in Linear Layout? Whats the main reason to use it?
LinearLayout layout = new LinearLayout(context);
In general, the Context you hand any View in Android is almost always an Activity. Like 99.9% of the time. However, there are cases where that's not what you want to pass. Such cases are those when, perhaps you're building part of the UI away from an Activity to be dropped into place later. You might not know what activity this will be attached to.
There are good reasons to make sure it is always the activity however, as is described in this article. For example, utilizing Activity makes sure the theme remains consistent.
Since a View does not need an activity, per say, to be created, we don't need to hand the Activity. Thus, the constructor only takes Context. This is a good example of ISP (The Interface Segregation Principle), in that, we're limiting the scope of what the View can access safely (what methods it can call on Context). We also increase the flexibility of the View API, because we don't require an Activity to instantiate views.
Activity isa Context as you can see in this.
A Context lasts the entire time your app is running while an Activity stops after your Activity ends. If the Activity ends before the LinearLayout object in your code, then a memory leak will happen since there is still a reference to that Activity.
I'm working on an android game that will have several levels and since each level will have the same code, I thought it would be good idea to create that code in a separate class and then using object of that class to use the code. However, all of my current code inside the main activity uses findViewById() to refer to different view in my app but I'm unfortunately unable to use this function outside of an activity inside just a normal class file. Are there any alternative ways of referring to views that I may be able to use in other classes?
Thanks
You have several options to do so, maybe you can pass the view itself as parameter but be careful to check if this view is in the correct context and if the view exists in the current screen to avoid some null pointer exceptions.
It's difficult to decide if this solution can even work without seeing your code
Total beginner here.
As I understand, fragments should communicate with each other through their hosting activities as a way to stay independent and reusable in other situations.
I’ve read that should be done by declaring interfaces in the fragment and implementing them in the activity.
Is that the best way to go about it “just” because you can make sure the activity is ready for that communication (it really has that method to deal with the communication)?
As I’m having a hard time wrapping my head around interfaces (and lots of others things in java/android, for that matter), could this be done without the interface? Could I get a reference to the hosting activity in the fragment and just call the activity’s method?
(fragment class)
Activity activity = getActivity();
activity.doThatThingToOtherFrag(String myString);
(activity class)
Fragment otherFragment = getSupportFragmentManager().findFragmentById(R.id.myOtherFrag);
public void doThatThingToOtherFrag(String string) {
//do something to myOtherFrag
}
Or is there something else about implementing an interface in this case that I’m not getting?
* EDIT *
Let’s say I reuse that fragment in another activity. As long as that activity also has a doThatThingToOtherFrag(String myString) method, I can get a reference to it through getActivity() and still call activity.doThatThingToOtherFrag(String myString) from my fragment, right? I wouldn’t have to change anything in my fragment code -- or am I’m missing something here?
I guess my question should be: is the interface there only to MAKE SURE the/any hosting activity implements a doThatThingToOtherFrag method? Or is there something else I don’t know about interfaces in this situation? Thanks for the help!
"Program to the interface." is a common maxim of object oriented programming. You can certainly just communicate with the activity directly without using the interface. However, this create a tight coupling between the fragment and the activity.
Consider a situation where you want to reuse the same fragment in two different activities. Using interface allows the flexibility to do this.
Answer to edit:
As long as that activity also has a doThatThingToOtherFrag(String myString) method, I can get a reference to it through getActivity() and still call activity.doThatThingToOtherFrag(String myString) from my fragment, right?
I assume you mean something like this:
Activity activity = getActivity();
activity.doThatThingToOtherFrag(String myString);
This won't compile because Activity doesn't have a method named doThatThingToOtherFrag(). However, if you do
FragmentCommunicationInterface activity = (FragmentCommunicationInterface) getActivity();
activity.doThatThingToOtherFrag(String myString);
now it will compile. This has yet another problem: what if the fragment where this is called was added to an Activity which doesn't implement FragmentCommunicationInterface. Now you will get a run-time error when you do the case.
One possible solution to this is to take a FragmentCommunicationInterface as an argument to the fragment's constructor:
public class MyFragment extends Fragment {
private FragmentCommunicationInterface communication;
public MyFragment(FragmentCommunicationInterface communication) {
this.communication = communication;
}
}
Now you create a fragment with
MyFragment frag = new MyFragment(this);
Another advantage to using an interface is that the interface can be implemented by any class not just classes which extend Activity. This allows even more flexibility than I hinted above. It allows you to organize the code to communicate with the activity or other fragments in any way you want.
It's not really necessary, but it may be desirable.
In general, interfaces help code not depend on the class whose code you call. You don't really care which Fragment class you're invoking, what you really care is that whatever you're invoking, it needs to have the ability to doThisOrThat() -- so that's what you put in your interface.
This decoupling is actually about helping to use polymorphism. Say your code may use two Fragment classes where you now use one, and both ca n doThisOrThat(). In that case using an interface will help you write cleaner code, because you won't need to write duplicate code to invoke the same method, except for changing what you cast it to.
Anyway, in order to really decouple you classes, you might want to learn about EventBus (doesn't matter which implementation).
This way you can make your fragment work with any activity that implements the interface. This completely adds to the independence and reusability you pointed out in your question.
If you would use the activity class's method to 'communicate' you would not be able to make it work (interface with) other activities because they are of a different class.
One good reason not to do the way you implemented as above is loose coupling. It is a program design pattern to create well-designed software. I am not gonna create a new discussion of it here since a lot of other discussions are available in StackOverflow.
What is "loose coupling?" Please provide examples
Please take time to understand this concept as this will save you a lot of time as a programmer.
Cheers!
Interfaces are best for communicating two fragments, 2 activities or communicate with any class, because interface triggered at same time when other want to communicate.
This might not make much sense in terms of Android SDK, but, in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes. I never come back and check for anything in main.cpp afterwards.
But in Java, Android SDK, you have to override dozens of methods in main activity and all of that takes place in one single file. Example:
I have a MainActivity.java and SomeTest.java files in my project, where first is default MainActivity class which extends Activity, and SomeTest.java contains class that declares and runs new Thread. I initialize SomeTest class from MainActivity.java and pass a handle of the activity to it as a parameter:
SomeTest test = new SomeTest(MainActivity.this);
And having the handle to MainActivity, I proceed doing everything from this newly created thread. When I need to update the UI I use runOnUiThread() to create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged() in my MainActivity.java and notify the thread from there, as getWidth() and getHeight() will only have values when ListView is actually displayed on the screen. For me it's not a good practice to make such connections ('callbacks', if you will) from MainActivity to that thread.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
As I said, might not make much sense.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
onWindowFocusChanged() is a callback method. It is called on the activity. You cannot change this.
And having the handle to MainActivity, I proceed doing everything from this newly created thread.
That's generally not a good idea. Using a background thread to, say, load some data from a file or database is perfectly reasonable (though using Loader or AsyncTask may be better). However, usually, the background thread should neither know nor care about things like "the width and height of the newly created ListView".
You are certainly welcome to migrate some logic out of the activity and into other classes. You might use particular frameworks for that, such as fragments or custom views. However, the class structure should not be driven by your threading model. For example, let's go back to your opening statement:
in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes
However, in C++, you would not say that you are locked into only ever having two classes, one of which is operating on some background thread. While you may have a class or classes that happen to use a background thread (or threads), the driving force behind the class structure isn't "I have a background thread" but "I want to reuse XYZ logic" or "I wish to use a class hierarchy in support of the strategy pattern" or some such.
Personally speaking Context idea taken from Android SDK seems to be messy. What you are describing comes from too much responsibility intended for Activity. That's why you need to track a LOT of things inside single file (Activity's life cycle, getting Context instance in order to show Dialog etc.). I don't think there's perfect solution but I would recommend using:
Fragment subclasses which are helping to divide your screen (and so on logic) into seperate parts
3rd party frameworks/libraries like AndroidAnnotations, RoboGuice, Otto which are perfect tools to avoid spaghetti code
if you would like to perform some UI updates from another class, consider using an AsyncTask passing it the Views you need to update. Let me know if you need an example
I read everything and understand your statements, I can see you've been doing programming for sometime but apparently is just starting with Android, I've done a lot of embed systems before so I totally get the concept of having a software that looks like:
void run(){
object.setup();
while(true){
otherObject.run();
}
}
But there's one fundamental flaw on the you logic of your question:
Android programming is a different programming paradigm from C++ and from computer programming and you should understand its specific paradigm instead of assume what is good practice from other paradigms.
Quote from you: create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged().
From that I can see that you've really trying to do Android stuff on a way that is not recommended on an Android context. A ListView you can easily implement from the XML layout setContentView(int) and use the Activity onCreate to instantiate any threading (AsyncTaskLoader) framework to load the data in background and deliver it back to the UI.
That doesn't mean that all your code will be dumped in one file making it a mess. This little example I put you can do with Activity that implements the loader callbacks, a separate class with the loader, a separate class with the data loading work, a separate class with the data adapter, the activity is just a central piece that organise and manage those classes on the correct moment of its life-cycle and at no point you need to call onWindowFocusChanged() and still have a nicely organised code.
Apart from that please refer to CommonsWare answer as it's usually cleverly written and correct.