In lot of examples I see, all the activities and fragments extends from base activity and base fragments. 2 questions:
When should I use it?
What kind of code should go in it?
Usually I use a base Activity/Fragment when I need to do some work in some of life-cycle callbacks of all of my Activitys/Fragments.
For example if you use Butter Knife (very recommended), you need to call Butterknife.bind(Activity a) after calling setContentView. So it's better if you create a base activity and extend the setContentView method in it like this:
#Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
ButterKnife.bind(this);
}
In child activities when you call setContentView at the beginning of onCreate (after calling super.onCreate), ButterKnife.bind would be called automatically.
Another use case is when you want to implement some helper methods. For example if you are calling startActivity multiple times in your activities, this would be a real headache:
startActivity(new Intent(this, NextActivity.class));
You can add a start method to your base activity like this:
protected void start(Class<? extends BaseActivity> activity) {
startActivity(new Intent(this, activity));
}
and start the next activity like:
start(NextActivity.class);
Other activities can extend BaseActivity. If you define common elements in BaseActivities and all other activities extend BaseActivities, then all activities will have these common elements, for example: custom menu, custom bar, design layout or some query logic...etc.
Similar with BaseFragment. I usually log onCreate, onAtach, onPause events in BaseFragment. So I see these logs in all other Fragment that extend BaseFragment. Also, you can very easy and in one class turn-off these logs for all fragment. (useful before publishing realise)
When we need Global error handling we can use base activity/fragment.
Related
I am new to both Android and Java (as well as OOP), so forgive me if this is super noobish. In going through the Android tutorial on a first app, the following code is written:
#Override
protected void onCreate(Bundle savedInstanceState){...}
I have read that #Override is overriding the default onCreate call and that, if you don't override, you can't specify which activity to use. That's all well and good, but in the interest of understanding, what exactly is the default activity if activity_main is not in the case that you don't override onCreate?
I think what you are asking is what does the base class onCreate method do, and what happens if you don't override it. You can look at the source code for Activity here, or the AppCompatActivity here to look at what is in the base class. Notice that a typical implementation in an app looks like
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// other custom setup code for your activity
}
That first call to super.onCreate still calls the base class onCreate method (the one you are overriding), so you're not replacing what's in the base class, but adding your customizations specific to the Activity you are creating. That call to super does a number of Activity setup things that you always have to do. It doesn't associate the activity with any layout file (which is done by the setContentView call), so it wouldn't display anything from your xml files without you adding the setContentView call. There is no default xml layout file it would use.
I believe you mean the default Activity layout?
If you don't set one in onCreate with setContentView I think you simply won't have one.
I have a DialogFragment successfully working with my MainActivity. It calls the activity's doPositiveClick() method with
((MainActivity)getActivity()).doPositiveClick()
So far so good, but now I want to re-use the same DialogFragment with SecondActivity. I have experimented with the syntax of the above line but I still have not found a way of replacing MainActivity with something that could denote MainActivity or SecondActivity depending on which called the DialogFragment. I have had both activities implementing an interface with doPositiveClick() but still I have not hit upon the right syntax to satisfy my requirement.
Let me be clear: I am asking a yes or no question. Can I adjust the above line, so I do not have to involve a Listener on an interface? Is yes, how? If no, fair enough.
Interface is the best practice for communicate with the fragment to activity ( not opposite ).
You can just make a parent activity implement your interface and make your mainactivity and secondactivity child. So you dont need to implement. You can just override the methods. So which activity make the fragment, that activity override method will trigger when fragment calls. I hope i understand your problem truly and answering truly. Any question please comment it. So i can answer via comment and also i can edit my answer.
Update: Simply yes :) In your fragment onAttach method you can control instance of the which activity create this fragment. I hope this will make you satisfied.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof MainActivity) ...
if (activity instanceof SecondActivity) ...
}
I have a ViewPager of 3 fragments. All 3 fragments are of the same type, with identical layouts, but they are to hold different (text) information. I am trying to create my activity, where I create the fragments and prepare the text data that I will populate my fragments with. However, I can't seem to work with the fragments from within my activity. All the activity's lifecycle methods are executed before the fragment lifecycle methods. So if I try to update a textview in a fragment from within my activity, it won't work, because the textview is null in the fragment.
I'm going to need to make periodic updates to the fragments, so passing the data as a bundle is not an option. Plus, since I'm passing lots of text, I'm using a StringBuilder object, which is not something I can pass in a bundle (unless I make it Parcelable, which I don't want)
I think I could run a method from within my fragment class that would execute during fragment creation, but that means all 3 fragments would run this method. That's not really the level of control I'm looking for.
Is there a neat way to make this work?
Thanks
Keep references to your fragments, and let them all implement an interface with a common update-method. As an example, let's make it super clear and call the interface Updatable with one method called 'update':
public interface Updatable {
public void update(String text);
}
Now, in your Activity's onCreate, save references to your Updatables there (i.e. when you lookup or instantiate your Fragments).
It should now be trivial to update your Fragments when necessary from the Activity. Needless to say, the fragment implementation of the update code needs to do the actual update of the TextView(s).
If the update implementation is exactly the same for all your Fragments, your could save some lines of code and make a base class which implements Updatable and extends Fragment.
you might able to populating fragment fields during onActivityCreated(Bundle savedInstanceState).
Refer to this site for more information about fragments' life cycle:
http://developer.android.com/guide/components/fragments.html
You should consider using Observer pattern... there is a really great implementation which you can include as gradle dependency called EventBus:
https://github.com/greenrobot/EventBus
You can use Otto Bus to send data to your fragments from your activity.
http://square.github.io/otto/
Create a new bus in you application class
Bus bus = new Bus();
Create an event that contains your data which you'll pass to fragments.
bus.post(new MyDataEvent(data));
Register your fragment in your fragment's onResume() (Do not forget to unregister in your fragment's onPause())
bus.register(this);
And get data with subscribe in your fragment
#Subscribe
public void onDataReceived(MyDataEvent event) {
// TODO Do what ever you want
}
I hope this'll help you.
I have 2 activities in my project, lets say Activity A, and Activity B. Both A and B extend the same superclass: BaseActivity.
We know that in this case, lets say if the Activity A is opened, then the superclass method onCreate() is called, and then the Activity A's onCreate() follows.
Being in the onCreate() method of the parent BaseActivity class, how can I determine which child activity has been started?
I would suggest a different approach. Basically don't do inheritance. Use composition instead. Remember most operations that you think you need to extend for really just need a reference to the context. Activities extend from context. So really you can provide most base functionality in any class that has reference to an active context. No need to do inheritance at all.
So if you want to share some functionality between ActivityA and ActivityB just put it in HelperC
HelperC.someOperation(Context c, otherParams)
HelperC can do anything that some base activity could do. Ultimately the base activity will never exist any way. It will always be an instantiated version A or B
I don't think you should do it this way.
As far as I remember the idea of extending, superclass method should contain only universal code. Puttin the differenting code in child classes would be much easier to do and as I believe more proper.
You can initilize some values in parent onCreate(), and then re-set it in childs'.
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.
}
}