I'm having an application with different views, and when I'm "flinging" at right or left another view pops in and the other slides out. Most of the application is based in that activity.
Since every view has buttons and lists (which you are supposed to interact with), the activity class is getting rather big and I was thinking of separating it. But which is the best way to do that?
Should I create classes that gets the activity context so I can declare the buttons value (findviewbyid()) etc. or is there another way to do this.
Is there a danger in sending the activity context? Is getApplicationContext() better to use for a time like this?, or should I just keep working on the class which is getting quite big?
Maybe there is a better way to do this?
I think the best way to do this would be to create a class that extends the View, and put all your child views in there. You'll still have to pass your context, but this way it'll be managed properly by the parent class.
I had a similar dilemma:
Safe to pass instance of an Activity to another object?
Related
I am working on android application and some team members suggested using one activity and one parent layout for the whole application and each time we need a new screen we just inflate a new layout in the parent layout and destroy the old one.
I on the other hand think that using fragments would be the way to go.
Do you think one way is better than the other?
I would be grateful if you can think of solid arguments to support your claim.
Thank you
UPDATE:
We are using MVC in our application. They want to create a new class for the view while i opted for using the fragment as my view. As it stands now the application has one activity and one layout. To change the view we are calling the same layout,removing its child views and inflating the new view .I dont see how that would be better then just using the fragments as views
I think most Android developers will tell you to use one or more Activities or Fragments. But why?
Basically, because one Activity which is responsible for each and every View in your app would be something like a "god object". This is considered an antipattern, I suppose because it may fast become a maintenance nightmare.
The Android pattern of one Activity and several Fragments on the other hand is following the Single Responsibility Principle, so your code is easier to maintain. All the more so because Android-specific things like saving state on configuration change are much easier to implement if you are able to use the built-in methods.
I have a little app wich contain MainActivity and two subclasses of View - FirstScreenView and SecondScreenView.
Now MainActivity manages both subclasses and output them successive.
I want to show both classes in one time in a one screen (in this layout - firstscreen.xml that is used instead of main.xml now. main.xml does not exist).
I know that this challenge can be overcome by applying the fragment. But my classes extends View, not Fragment.
May two View classes work as two Fragment in one screen?
Please, tell me in what way and how should I solve this problem.
Thank you (and thanks Google Translate).
Talking from a UI perspective, the app will look the same. Talking from a functional perspective, the app could do the same. The only difference is that if you use fragments, you will have to manage both lifecycles.
I rather preffer what you have done, working with these two views. Remember that if you work with custom views, it is a best practice to delegate its logic to the activity, something you will relay to the fragmeents in the case you use them.
We use different activities to navigate through our app. One of them is very complex and contains a lot of nested views/images etc, so when I usestartActivity(intent1) in the activity before it, there is a short delay and it feels/looks laggy.
All the information needed to create the content views is known in advance.
So my question is: is there a smart way to prerender/preload the activity or its content view?
As i figured the intend only holds information about the next activity but no instance of the activity itself, so i assume there is no way to tell the intend to create the activity before i call the startMethod.
One idea i hat was to create a static view before starting the activity and set this view as contentView in the onCreate() method. But it seems like a bad hack to me.
Thanks in advance!
The best solution would be not to start a completely new activity but using a ViewPager or ViewFlipper. Switching between Views should be then nearly instantaneous and you also get the chance to easily apply animations.
If that is not possible you could start a new activity but put a ViewSwitcher in there. The first View would be a progress bar. The second view is inflated and added to the Switcher in a background thread.
I know there have been quite a few questions about this, however, I'm still struggling to understand what role the Activity class should play when implementing the traditional Model-View-Controller design pattern on Android?
My gut feel is that it should be the Controller, however that means a one-to-one relationship between UI screens (since you must have one Activity per screen) and controllers, which defeats the point of MVC's loose coupling between the different components.
You are right. The xml interfaces could be defined as the View and your other class working with data as the Model.
The activity receive all the events and user inputs from the View ,so, we can easily said that it is the Controller.
But let's be clear , it's not a perfect (does it really exist ?) MVC
Have a look to this question , and more specifically , the first comment of the accepted answer, it may be useful
Activities can make competent controllers and, with fragments, you can also implement hierarchical MVC. Most of making MVC work is up to the programmer, because even in the strictest frameworks you can still find ways to do crazy things.
Android does not have a good architecture and it does not follow the MVC design pattern.
The best way to conceptualize Activity in MVC is as a View (with some controller logic) because it gets destroyed every time that a configuration change happens, such as a screen rotation or locale change, losing all its state.
The controller in this case would be the Application object, because it is your bridge to access the view (Activity and its GUI components) from code outside the Activity context. You have to use singletons so that there is only one Application object at a given time, otherwise there will be one Application object per process.
The Application object is not a good place to store the Model because its life cycle is detached from that of the Activities. It can get destroyed and recreated at any point of an Activity's life cycle (while the application is in the background) without causing it to restart, and then all its variables and references not assigned inside its onCreate() method will become null.
The Model therefore has to be stored on a GUI-less, headless fragment with setRetainInstance(true), that is linked to an activity, and has to be re-attached to it every time the activity is recreated. You have to use a fragment manager to ensure you are recovering the retained fragment and not creating it anew. This is also the best place to run background tasks, though you can also run them in the Application object. Never run tasks on an Activity as they will get destroyed on configuration changes.
I think the confusion may come in with defining a view as XML and so the Activity is mistaken for being the view. It's not. You pass the view (your XML layout) into the Activity which will then inflate the views contained within the XML layout. Your activity also passes data (models) into your views (EditText, TextView, extended version of base views, etc).
If you really want MVC then you can achieve this simply by setting up your view in an XML layout, create a view object which extends from your root view (if it's a RelativeLayout extend from that). From there you add your accessor methods and different logic needed for that view and you can then add unit testing around that.
In the Activity you will no longer pass in the ID of the layout and will instead do something like this:
CustomView customView = new CustomView(...);
setContentView(customView);
...
Of course almost all apps won't do this and you really don't need to do this. Calling findViewById is enough to link to that view object and call on the methods it has. Which in my mind, is MVC.
I have a SlidingDrawer that is referenced in all of my activities. The drawer is quite detailed and has a deep hierarchy of views. Currently I have all of my activities calling the application context upon creation to receive the singleton copy of the drawer. When an activities onPause is called, it removes the drawer from its top level ViewGroup. This works, but I don't know if it is the best way of doing it.
Also an issue I'm having is context usage. The SlidingDrawer has some buttons that fire off some dialogs. Knowing that I can't pass the application context, I just created a OnActivityChangeBroadcaster and Listener which changed the references context for the drawer. But even with this the dialog always appears in the launcher activity.
Does anyone have any thoughts or wisdom on the matter?
This works, but I don't know if it is the best way of doing it.
You are leaking memory. Never pass widgets between activities. Never put widgets, or anything else with a reference to an activity, in an Application object or static data member, unless you are going to null out that reference when the activity is destroyed.
Does anyone have any thoughts or wisdom on the matter?
Recreate your drawer in each activity, please.
My approach would be to decouple the UI from the data. If many of your Activities use the same SlidingDrawer, I would separate the data that the SlidingDrawer is displaying into its own [non-UI] class so that it exists in only one place, and have each SlidingDrawer instance populate itself from that data. You can define your SlidingDrawer in XML once and <include> it in the all the layouts you need.
Then I would have one function that populated the SlidingDrawer with the data from your separate class (accessible via a singleton object or by making the data static). To achieve that you can either make a static method that takes the SlidingDrawer to populate as a parameter (public static void loadSlidingDrawer(SlidingDrawer destinationView) {...}), or you can extend SlidingDrawer and make that a class method accessible by each instance.
CommonsWare is correct, you'll be leaking memory all over the place with your current strategy. UI elements need to have the flexibility to be destroyed and recreated constantly, so it's a really good habit to get into to separate all your data into non-UI classes that you UI simply accesses to display. This decouples everything nicely and allows the framework to function efficiently.