I have 3 activities with the same toolbar. I would like to avoid copying code on each activity. I know I can use <include> tags in every layout in order to reuse the same layout for the toolbar. Now I would like to share the event handlers for each button of the toolbar in all the activities. I am thinking of making a toolbarActivity which extends Activity class and the 3 activities extends toolbarActivity, so in onCreate method, when I call base.OnCreate, all the event handlers would be defined. But, SetContentLayout was not called yet, so base.OnCreate will not find the buttons. Remember the 3 activities have different layouts. Do you know the best way to reuse code in order to avoid copying all the event handlers in OnCreate method for every activity and allowing me to override some functionality?
Android is used on mobile devices so at development time their is no way to know the size and dimensions of the users device. On large devices many UI elements can fit. On smaller devices few UI elements can fit. Your question relates to this dilemma and therefore has many possible answers. Logically for code to work it must exist inside the source, ie you could cut and paste, a bad solution because you end up with many versions of this "same" toolbar or you could refer/reference one "external" toolbar. Fragments come to mind as does having a separate source file. UI source files can be thought of as pairs. Java for dynamic elements and xml for static. So in summary just reference an external fragment that has implemented your toolbar.
If you keep the naming conventions for the buttons and other things in each layout that are tied to the references in your activities then you should have no problem.
For example if you have a '#+id/login_button' in one layout then just use the same convention for the same type of button in the next one and youll be fine.
You could define a base activity which all your other activities extend, and make it implement a click listener (or whatever interface you are using to listen for button presses). You can check the Id of the clicked view and thus provide a callback to perform whatever logic you want.
public class BaseActivity extends Activity implements OnClickListener {
public void onCreate() {
myBtn.setOnClickListener(this);
}
public void onClick(View v) {
if (R.id.my_btn == v.getId()) {
onFoo();
}
}
protected void onFoo() {
// TODO handle foo
}
}
You can then override the method in your subclasses if you need to provide different behaviour.
public class DifferentActivity extends BaseActivity {
#Override protected void onFoo() {
super.onFoo()
// TODO handle foo differently
}
}
Related
I'm not sure the best way to go about what I intend to do. I have an app that involves three fragments, each navigated to by a single activity that has a navigation drawer.
I have a text to speech class that initialises the text to speech engine. The problem is, is that it needs to be used by multiple different fragments. My idea was to create an object of the TTS class in the main Activity and extend functions so that they can be called by the fragments, like so:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTextToSpeechService = ((NavigationActivity)this.getActivity()).GetTextToSpeechService();
}
The problem I see here is, what if I need to do something such as change the language within one fragment. That would mean I'd have to expose another function to set the TTS class within the activity, which doesn't seem right.
What is the best way to go about this?
There are three options:
Inherit from application and store singleton there. You can see how to do that here.
Create started service and use it from activity.(not bounded) See the link.
Store language setting in SharedPreferences and apply them to textspeech engine in activity lifecycle methods (onResume method).
Services are designed for tasks which are not connected to UI. If it's too much work to be done you may find third option to be a candidate for this particular problem.
I'm contributing to my first large project and am struggling with a design decision. I have two fragments that populate a ListView and set a custom ArrayAdapter. Let's say the list items are emails, and the two Fragments are MessageListFragment and SearchMessagesFragment. The ArrayAdapter uses a ViewHolder pattern to inflate each message and attach an onClickListener to the "star" icon.
Now, regardless of which fragment I am in, I want the onClickListener to do the same basic thing: change the status of the email on the server to "starred," and determine if the email needs its position moved in the list (i.e. left alone if there are no filters, moved the to top/bottom if the emails are sorted by starred messages, or removed from the current list if the filter is only non-starred messages).
How can I create this behavior in a reusable manner so that I do not have to repeat this code in both fragments?
If I understood you need to perform an action triggered by one of the Fragments or both or further ones you should create an Interface ie:
interface MyCustomAction {
void triggerAction(boolean isTriggered);
}
Assign it to the Fragments and implementing it in the Activity responsible of Fragments
Declare Action in the Fragment:
private MyCustomAction myCustomAction;
Expose method to be assigned by Activity in the Fragment:
public void assignAction(MyCustomAction myCustomAction) {
this.myCustomAction = myCustomAction;
}
In the Fragment, when an onClickListner() is called, do that:
myCustomAction.triggerAction(true); //or False or what you want...
...and in the Activity:
myFragment.assignAction(new MyCustomAction() {
#Override
public void triggerAction(boolean isTriggered) {
//Doing something can be triggered by any Fragments using the same Interface
});
One way would be to create a separate class, which implements View.OnClickListener , and then pass an instance of that class to the setOnClickListener(...) method.
Im not entirely sure I fully understand you, are you saying that you have two onClickListeners and you want them to do the same thing without repeated code? If so, you can simply put the repetitious code in a subroutine and call it from both listeners. However if you mean that you have one onClickListener and you want it to listen for two different actions, then you can change those actions so that they act on the same listener. I am not sure what language you are using so I could not tell you how to do this but it should be fairly simple.
If I need to do 10 similar activities, is it better I do:
10 activities and 10 layout?
1 activity and 10 layout?
1 activity and change the UI with visibility gone/visible?
I need an answer for:
performance
formality
If you use multiple activities, you will get the advantage of using the android activity stack mechanism. So if you want your users to be able to navigate with the back button, then it's the best bet.
Also, if your activities are very similar, then you can implement common code in an abstract class, and make your 10 activities extend this common class, thus sharing some code.
public abstract class CommonBehaviorActivity extends Activity {
protected void buildCommonThings() {
((TextView)findViewById(R.id.title)).setText(getTitle());
((ImageView)findViewById(R.id.image)).setDrawable(...);
}
abstract protected String getTitle();
}
public class MyActivity1 extends CommonBehaviorActivity {
...
protected String getTitle() {
return "Title 1";
}
}
and so on...
Edit : Added some sample code to show how to share things that you want to see in every sub-activity. For example, if you have a list in each activity, then you can define a specific adapter in the sub-activities in a getAdapter() method, and bind your list to this adapter in the CommonBehaviorActivity as well as configure it (bind listeners, and so on...)
On the other side, if you want to have a very fast switch between your activities, and you don't need to be able to go "back" with the button, then visible/gone view is maybe better.
Making several activities will make your code more readable and easier to debug as you won't deal with excessive if and else conditions. There will be no performance overhead: Activities load fast and Android manages the backstack and free up memories by killing paused activities when needed (which won't be the case with a single one).
If your activities are similar, you can put features in separate classes and re-use them across activities. Idem for layouts, you can design them so you can re-use common parts.
You can also use fragments if you want to for display dynamic UI. You can change content in fragment dynamically or you can change the fragment itself. You can always keep certain fragment visible and others inactive. In this case you will only need one activity and multiple fragments.
It will depend how you want draw UI of your app. Fragments examples are available is Here
I need to create a base class that extends Activity which does some common tasks in my application and extend my activities from it,in the following form:
public BaseActivity extends Activity{....}
public SubActivity extends BaseActivity{...}
in SubActivity I need to give values to some variables and UI components defined in BaseActivity, I may need to define a different layout for SubActivity according to some flag value, also(in SubActivity ) I want to execute asyncTask that is defined in BaseActivity.
is this possible? if yes, is there any tutorial that may help?
thank you in advance
What exactly are you trying to achieve? Having two different activities with a common ui, except for some variables or parts of the layout?
In this case, I suggest having a base abstract activity, and two concrete inherited subclasses. You define all the common behaviour in the base activity, and have abstract methods for the differences, which you then override in your actual implementations.
For example, for two activities with different layout resources:
public abstract class BaseActivity extends Activity {
#Override
public void onCreate(bundle) {
super.onCreate(bundle);
setContentView(getLayoutResourceId());
}
protected abstract int getLayoutResourceId();
}
public class Activity1 extends BaseActivity {
#Override
public void onCreate(bundle) {
super.onCreate(bundle);
// do extra stuff on your resources, using findViewById on your layout_for_activity1
}
#Override
protected int getLayoutResourceId() {
return R.layout.layout_for_activity1;
}
}
You can have a lot more abstract methods, for every bit you want specific to your subclasses.
Doing that is, in my opinion, a lot better than having a concrete subclass to a concrete superclass: that can lead to many problems and is usually difficult to debug.
This question already has very good answers.
However. my answer is for those people who are looking for some working example.
Here is the full working -> CODE
We are not doing anything new here, it is just like any other inheritance scenario (You want some common behavior at multiple places but you want to write that behavior only once).
ADVANTAGE:
It does provide better code readability, maintainability and blah blah. But are not after these -ibility, They won't matter to you if your brain runs like a gazelle.
We are after the real power of inheritance “CONTROL”. (That’s what happens in real life too. Parent controlling child :) ) .
In my example, I have two Activities MainActivity and OtherActivity.
Both Activities has a different layout but I want both of them to start with some animation or some welcome message.
Our first task is to find out the common behavior.
here -> Start Activity with animation.
We have found the common “thing”, now we will write that behavior in BaseClass (AnimationActivity).
MainActivity and OtherActivity will inherit AnimationActivity.
So the code would look like `
BaseActivity
AnimationActivity {
startAnimation()
{
....
}
}
Child Activities
MainActivity extends AnimationActivity{
}
OtherActivity extends AnimationActivity{
}
This design approach provides a lot of Control and Flexibility (POWER OF MODIFIER).
1) CONTROL: Keep animation method inside onCreate()
When you decide that Activities should be started with Animation.
Keep your method inside onCreate(Bundle bundle) method. Now just by changing the modifier, you can control the child Activities.
If you keep modifier as
final: Child activities will start with parent Animation.
abstract: Child activities will have to give their own animation.
no modifier: Child activities can have their own animation by overriding animation method, Otherwise the child will have parent animation.
2)Flexibility: Don't keep animation method inside onCreate()
You can provide child activities flexibility by not keeping animation method inside onCreate(Bundle bundle).
Now activities can have the flexibility to have parent Animation or their own animation or no animation at all.
Hope it helps.
Happy learning.
`
Yes you can, you should just keep in mind the basic inheritance rules. You will inherit the inner AsyncTask activity and the properties defined in the BaseActivity if you make them protected instead of private. From what I see now I think you should make BaseActivity an abstract class, as only instances of subActivities will be really used.
You should just start and try it, it'll come and work easier than you think. If you stumble upon any problems, just ask.
I have found an easier way to #Guillaume's solution. Set ContentView only once in your BaseActivity and do not set it in the activities that extend it:
public abstract class BaseActivity extends Activity {
#Override
public void onCreate(bundle) {
super.onCreate(bundle);
setContentView(activity_main);
}
}
public class Activity1 extends BaseActivity {
#Override
public void onCreate(bundle) {
super.onCreate(bundle);
// setContentView(activity_activity1) // Do NOT call this.
}
}
In Android there seems to be 3 common ways of handling button clicks, how much difference is there between the methods? And are any of them 'better' in some way?
The three methods I keep seeing are:
Anonymous class
Find the button by it's ID, then pass a new anonymous class to setOnClickListener, e.g. in onCreate
findViewById(R.id.myButton).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// .. Whatever
}
});
Implement OnClickListener
Implement OnClickListener and pass this to setOnClickListener, then use a switch statment based on the button ID, e.g. in onCreate
findViewById(R.id.myButton).setOnClickListener(this);
and implement onClick like
public void onClick(View v) {
switch(v.getId()) {
case R.id.myButton:
// ... whatever ...
break;
}
}
Use onClick XML atribute
In the XML layout for your activity, instead of giving your button an ID, use onClick like this:
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:onClick="buttonClicked"
android:text="Button" />
Then have a buttonClicked method in your Acitiviy like this:
public void buttonClicked(View v) {
// ... whatever ...
}
At the moment I tend to use the XML attribute, but that's just because it involves the least amount of code. When should I use the other methods?
The first two are the classic approaches. Which one you prefer is more of a general Java question than an Android question.
The third one was added later to make things easier.
Setting up a click listener on a button is very common task, but it
requires quite a bit of boilerplate code. One way to reduce the amount
of boilerplate is to share a single click listener between several
buttons. While this technique reduces the number of classes, it still
requires a fair amount of code and it still requires giving each
button an id in your XML layout file. With Android 1.6, none of this
is necessary. All you have to do is declare a public method in your
Activity to handle the click (the method must have one View argument)
Source
I've really always seen it as preference. I'm not sure there's any performance advantage to either other than the last two methods may be slightly faster since they're not creating objects at runtime.
The first option isolates the code to the single button so it's very easy to debug since you know only that code will be executed when that button is clicked. However, many buttons can cause initialization methods to expand to large sizes.
The last two methods put all button handling in one place which can be convenient and cleaner at times, but with many buttons you have to decipher which button was tapped by the user via the v.getId() method.
The last option allows you to easily specify specific methods for specific buttons so you can separate them out like that, but again you'll have many methods used for single purposes.
I've always used the inline method (anonymous class) for custom dialog windows that have buttons since it keeps the code with the rest of the dialog rather than in an activity or class. I just initialize the buttons of the custom dialog when I override the onCreateDialog.
I implement the OnClickListener on the Activity if the buttons are on the main window.