How to share on click handler between activities - java

Scenario, I have two activities, activity A, and activity B, they both extend from Activity, I also have a base menu xml on my ActionBar has onClick defined on a handler() method, how do I go about making this method available for my two activities without implementing it in both?, is making a common activity SuperClass the only way?

The generic answer is that you could either make a common superclass, as you say, or you could create a helper class, where each Activity class that uses the method would have:
public void onSomethingClick(View target){
MyActionBarHelperMethods.onSomethingClick(View target, /* whatever other things from this class you need */);
}
This can get kind of verbose if you have a lot of things you want to handle this way, but it's less verbose than implementing the same method everywhere. It will also be painful to implement a new item in your action bar this way (since you'd have to add the method to every Activity you want to use it). However, once again, it's less painful than having to modify the method in every place if you want to change it.
One way to possibly mitigate the headache when you want to add a new method would be to make each Activity implement an interface that contains all of the action bar methods you want them to have; most IDEs will realize you've added a new interface member and offer to add it to all of the implementing classes.

Related

Fragment to Fragment communication - why is the interface really necessary?

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.

Should I use an extra class or style the instance?

I'm using a UI framework which doesn't follow a strict MVC design. I create a component and add the appropriated properties to "style" this instance of a class. Some pseudo code:
Button bu = new Button();
bu.setCaption("Something");
bu.addClickListener(...);
bu.setAnotherProperty(1);
However, when do I decide to make an extra class instead of this whole setter block?
Like (pseudo code):
public class MyButton extends Button {
this.setCaption("Something");
this.addClickListener(...);
this.setAnotherProperty(1);
}
Is it a good practice to do it like this always? Is it a bad practice to do it in general? Or is there a special case where one should decide to create a class instead of a huge setter block?
Your MyButton isn't really (at least based on the code shown) a special type of button. It's just a Button with some parameters set in a certain way. Based on that I would probably not create a separate class, but factory methods that build buttons according to different specifications.
This has the added benefit that if you suddenly realize that you need 2 types of "special" buttons, you'd add another factory method instead of creating another class that's still basically just a Button with some extra make-up.
So instead of Button b = new MyButton(); I'd have something along the lines of (implementation style free) Button b = ButtonFactory.myButton();.
Do you use your custom button more than once? If so, then it would be good practice to create a separate class. If not, then generally it is not necessary.
Even if this custom button is only used once, I'd still recommend a separate class for "safe keeping".

Is it bad practice to pass the instance of an Activity as a parameter and finish() it from a different class?

I have a few Activities that use the exact same methods logout() and redirect() multiple times.
Would it be alright to use a separate class and mark these methods as static as follows:
public class AuthUtil {
public static void redirect(SessionManager manager, Activity activity) {
manager.redirect();
activity.finish();
}
public static void logout(SessionManager manager, Activity activity) {
manager.logoutUser();
activity.finish();
}
}
And call them from the activity by:
AuthUtil.logout(mSession,this);
Or should I be extending the Activities that use the method to a common Activity class and just put the methods there (except without the parameters since the methods wouldn't need them in that case)? However, I won't be able to do this if one of the activities extends FragmentActivity, another ActionBarActivity, which is actually the case for me...
Basically, I want to know if it's bad practice to call the activity's methods like that from a separate class body than its own? If so, what should I be doing?
No it is not considered bad practice - but choosing that route because it is easiest may well be a decision you later regret.
You should ask yourself the following questions:
Who is responsible for finishing the activity?.
Who knows when to finish the activity?.
Who knows how to finish the activity? (usually the Activity but be certain).
In your case it could be:
The activity itself
The session manager
The algorithm
Something else entirely
Once you have answered those questions you should have a good idea how to implement.
Remember that you could also create a third object, perhaps an ActivityManager that takes responsibility. It could hold a list of activities that need to be finished when the SessionManagercompletes the session. You may then have:
sessionManager.redirect(activityManager);
other scenarios could result in
// Make sure when the session completes this activity is finished.
sessionManager.registerAttachedActivity(Activity activity);
or
// Activity must finish when redirect completes.
activity.finish(sessionManager.redirect());
It really isn't as simple as good practice and bad practice it's more about doing it right.
Would it be alright to use a separate class and mark these methods as
static as follows
No. It would make very difficult to figure out where are the activities being finished by looking only at the source code of a given activity. And its also hard to see in what thread are those methods running for instance. And finally, because they are static, you'll have to add a new method if an activity needed to perform additional or different actions when redirecting or logging out.
Or should I be extending the Activities...
In my experience it is not a good idea to tie activities to an inheritance hierarchy, and you named a few good reasons for not doing so. If you need code reuse try to use composition instead.
I'd always call Activity.finish from the very same activity, in fact I'd like to have the whole lifecycle picture contained in the activity's code. But this is just what my guts tell me, there's no definitive correct answer to your question.

A BaseActivity for all activities, possible?

There are methods and attributes I would like to share across activities. E.g.
public class BaseActivity extends Activity
would be the parent for another activity
public class MainActivity extends BaseActivity
BUT if the child activity is a e.g. ListActivity this is not possible, right? Do I need a base class for ListActivity, too? This would be redundant code.
I could transform the ListActivity to an Activity, but this would be more code then necessary.
Any suggestions?
Yes, you're right. As java does not support multiple inheritance, a class can only have one base class.
But you can work via delegation instead of inheritance: Put your methods into a separate class (which does NOT inherit Activity) and use instances of it in your activities. Then you can reduce the redundant code (creating and holding the instance) to a minimum.
See also:
http://sourcemaking.com/refactoring/replace-inheritance-with-delegation
How do I implement multiple inheritence in Java
For the ListActivity case I would create a BaseListActivity that extends from BaseActivity. The BaseListActivity would contain a getListView() that returns the ListView if you really-really need it, a protected method setAdapter() that receives an Adapter/ListAdapter. You could also create some protected methods for enabling to show the empty view, to enable this behavior and to return the ids for your empty view and ListView. By default these should point to android.R.id.list/android.R.id.empty. But you can override that in your child activity.
In the end it's a matter of OOP and not that much of Android specific. If you check the implementation of ListActivity you'll see how simple it is to make your own BaseListActivity implementation. In the end it's more important to have a consistent and robust class hierarchy.
I am using my Activities this way, and I'm really happy I'm doing it. Of course you have to make some changes (like the ListActivity you mentioned in your question), but it has more advantages then disadvantages in my opinion.
In my app I don't have to worry about sending Analytics data every time I create a new Activity, and I also don't have to worry about setting up BroadcastReceivers I need in every class, I just made my BaseActivity abstract and have an abstract function what I call every time my BaseActivity gets a broadcast.
if you want to share some methods the best way it to impelement an interface or make an abstract class for baseactivty.
As others have pointed out, you need to use composition, since multiple inheritance is not possible in Java. This answer to a related question explains how to do this in the case of Android Activities.

Extending a class--how do I avoid having to create multiple classes?

The question doesn't really make sense, but this should help explain it better.
I'm currently using the IOIO, and it works like this:
public class MainActivity extends CustomIOIOActivity {}
From there I can call classes I've made in CustomIOIOActivity, which extends Activity.
The problem I'm running into now is that I have to inherit classes different from just Activity. For example, FragmentActivity.
Is there a way for me to create a custom IOIO activity which I can use for when I extend Activity and FragmentActivity? I don't want to have to make two essentially identical classes, which is what I am doing right now--seems silly. I'm not very familiar with Java, perhaps this is easy to do.
In Java you can't inherit class from more than one superclass. In order to achive your purpose, I would advise you to move all common logic to another class(IOIOHolder, for example), which would take an Activity parameter in constructor. Later you can create two different classes extending Activity and FragmentActivity, each containing an exemplar of IOIOHolder and using it for it's own tasks. By using this approach you can write IOIO code once and use it in any activity you want.

Categories

Resources