What is the benefit of using Fragments in Android, rather than Views? - android

When developing for Android, you can set your target (or minimum) sdk to 4 (API 1.6) and add the android compatibility package (v4) to add support for Fragments. Yesterday I did this and successfully implemented Fragments to visualize data from a custom class.
My question is this: what is the benefit for using Fragments as opposed to simply getting a View from a custom object, and still supporting API 1.5?
For example, say I have the class Foo.java:
public class Foo extends Fragment {
/** Title of the Foo object*/
private String title;
/** A description of Foo */
private String message;
/** Create a new Foo
* #param title
* #param message */
public Foo(String title, String message) {
this.title = title;
this.message = message;
}//Foo
/** Retrieves the View to display (supports API 1.5. To use,
* remove 'extends Fragment' from the class statement, along with
* the method {#link #onCreateView(LayoutInflater, ViewGroup, Bundle)})
* #param context Used for retrieving the inflater */
public View getView(Context context) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.foo, null);
TextView t = (TextView) v.findViewById(R.id.title);
t.setText(this.title);
TextView m = (TextView) v.findViewById(R.id.message);
m.setText(this.message);
return v;
}//getView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
View v = inflater.inflate(R.layout.foo, null);
TextView t = (TextView) v.findViewById(R.id.title);
t.setText(this.title);
TextView m = (TextView) v.findViewById(R.id.message);
m.setText(this.message);
return v;
}//onCreateView
}//Foo
Both methods are very simple to create and to work with in an Activity that, say, has a List<Foo> to display (for example, programmatically adding each to a ScrollView), so are Fragments really all that useful, or are they just an over-glorified simplification of getting a View, such as through the code above?

The main reason to use Fragments are for the backstack and lifecycle features. Otherwise, custom views are more light weight and simpler to implement.
At first, I actually tried to build a phone/tablet app using custom views. Everything appeared to work across phones AND tablets, even switching from single panel to split panel. Where I ran into trouble was with the back button and life cycle. Since I was simply updating views manually...there was nothing keeping track of the history of views and their states. Therefore, the back button did not work as expected and it was difficult to recreate even the latest state during life cycle events, such as when rotating the app. To fix that, I had to wrap my custom views in fragments and use the FragmentManager so that the previous states would be saved and recreated.
I realized after answering that I posted to a similar question a year earlier: https://stackoverflow.com/a/11126397/618881

I'd say Fragments are useful in two scenarios: if you split up views on some devices/orientations and show them in two activities and show all the content in one on other devices. That would be a use case if you go on a tablet or maybe even in landscape mode on a phone: e.g. you show the list of items and the details on one screen. on a phone or in portrait mode you just show one part.
Another use case are reusable views. So if you have some views that are visible on different activities and also perform some actions you could put this behaviour into a fragment and then reuse it. Obviously you could probably do that with custom widgets too.
I wouldn't see any reason for using Fragments for every View and I guess it would just be an overhead. I'm only using them in the first use case and I'd say here it is a simplification.

Android introduced fragments in Android 3.0 (API level 11), primarily to support more dynamic and flexible UI designs on large screens, such as tablets. Because a tablet's screen is much larger than that of a handset, there's more room to combine and interchange UI components. Fragments allow such designs without the need for you to manage complex changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able to modify the activity's appearance at runtime and preserve those changes in a back stack that's managed by the activity.
Here you can read more.

Scenario Activity Split screen - We have One Layout and one activity which handle left right screen part
Scenario FragmentActivity we have One layout for Main screen, one for left one for right
Scenario one is good if you have simple application.
Scenario two is good if you want to have Multiple Fragments and multiple FragmentActivities
and you can combine each of those. Also you can make interaction between fragments.
I have split screen Fragmentactivity i can call it with 'Intent Extras' and tell to fragmentActivity which fragment are to be loaded. Fragments are good because they are not in manifest so you could make reusable fragments and FragmentActvity.
But it make your project larger. But if you make large project you can save many. Because you can use same Fragments or same Fragment activity.
And i thing that this fragments come little late so you must try to think in new way.
Maybe just try to convert your activity to FragmentActivity. Later try to find reusable code and make Fragment from it.
Its usefull but i dont know how right now. But i have some ideas.
This is always problem. Android Team made somethink and nobody know what is good for. Because we are hardly learn like it was and here it comes some new things.
In my opinion it is good but not for reason that google tell us.

Add one case when using Fragment or Activity over CustomView:
When you are using CursorLoader to observe certain views, ListView or TextView and want to update their display value whenever your ContentProvider's data updates at back end(most common case you have a service which updates your local database by polling data from remote database/cloud periodically)

One big thing all the above comments don't mention is that a fragment remains resident in memory even if Android kills the activity and restarts it when you do something like change the orientation of your device. This is done for performance reasons but can also lead to unexpected results if you were expecting fragments to be destroyed only to find that they are getting recreated out of nowhere.

Related

How to activate Talkback inside of an fragment's views?

I'm currently adding accessibility as a new feature inside my app.
My goal is that the user would be navigating it using the TalkBack service integrated by Android.
Everything is working well, since I'm setting content description on the elements that are inside my activity layout i.e.
<View
style="#style/custom.style"
android:contentDescription="#string/my_string_value"/>
This way, every time that my activity is displayed the TalkBack is reading the content description value.
I haven't had the same success using just one activity which is pushing several fragments on it. So if I try to set a content description on any element inside the fragment layout this is not gonna be read (automatically) till it detects a touch event (I'm expecting to the TalkBack does it automatically, just like the views that are in the activity layout)
In order to get a result as the one that I expect I this this inside the fragment class:
public abstract class myFragment extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
myCustomView = (LinearLayout) rootView.findViewById(R.id.duende);
myCustomView.requestFocus();
}
}
This haven't had success so far, same thing setting the accessibility as a content changed.
getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
Does anyone had faced a similar issue?
Not sure your still looking for the solution but for future seekers :) -
Many times the focus request works only once called from within a post/postdelay function.
Example -
myCustomView.postDelayed(new Runnable() {
#Override
public void run() {
myCustomView.setFocusable(true);
myCustomView.requestFocus();
myCustomView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
}
},1000);
While working with fragments, I like calling both the focuses, input focus, like called by the guy in the previous answer, and the accessibility focus because while implementing accessibility onto fragments you can get pass some irritating problems. hence this always does the job for me.
First, it's important to note that Fragments function no different than layouts within normal activities. Fragments are just a convenient way of structuring the code. What Android/the Accessibility APIs see if you code up your application as a series of fragments, or a bunch of layouts within a single activity is identical. That being said, I believe what you're looking for is the following:
What you need to do is move accessibility focus.
myCustomView.requestFocus();
is moving what I consider input focus. This will have no effect on TalkBack, and is in fact all but completely meaningless, unless you are using keyboard navigation, or we are talking about an EditText box. What you want to do is move Accessibility/TalkBack focus. This can be accomplished with the following line of code:
myCustomView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
NOTE: Please keep in mind WCag 2.0 criteria, especially when it comes to moving focus around on TalkBack users automatically. This can become very confusing for non-sighted users!

Android: Visual A/B Testing library

I am developing a small A/B Testing library for Android. Library will only be initialised in application class. I need to change TextView values.
I will store all the data fetched from the in a file. But I am not able to track when ever a TextView gets into view and moves it.
For example TextView A is in X Activity, TextView B is in Y Activity and TextView C is in Z Activity. Since the variable I have is Context, how should I change TextView A, B, C values.
I need to figure out which Activity is Visible. From the Activity I will be able to get root view. And I will iterate over child views and change value. But How should i listen to Activity Change.
Is there any other approach to this ?
I know this is possible as many A/B testing library are doing this.
Here you go, check out my answer over Here
As you've mentioned, hooking into the activity lifecycle callbacks via AppContext is the best way to start. From there, you'll have all of the information you could possibly need. Every time the activity switches, you'll have the Activity object, and from there you can get the root view and apply changes as necessary.
I would advise against an iteration over the views though! If you have the rootview, you can just do a findViewId(textview C id) on that root view and you'll grab your view!
Since you are building a library, you can expose a function which can be called after onCreate of each activity, which will give you reference of the activity. Once you have the activity, you can get it's root view and do whatever magic you want to do.
That's the only other approach if you don't want to register LifeCycle callbacks for activity. The application needs to enter your library at least at some point of time. Either you can make the application do manually ( above approach ) or you can override all life cycle events of all activities ( registering lifecycle call back ).

Android: is better to do many activities, or 1 activity that changes on the fly?

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

What is Bundle, View, Context?

Guys I have watched tutorial on YouTube about android it has 200 videos but didn't explain what is Bundle, View and Context.
1st question what is Bundle?
2nd question what is bundle inside onCreate method where that come from? what inside that bundle?
3nd question what is Context? what I found is that Activity extends Context, so is it right to say that Context is the activity itself? or the Context of that activity?
4th question what is View? what I found is that TextView extends View and other widgets like Button EditText extend TextView so it means they also extends View.
I also found that the syntax of Button, EditText and other widgets is this...
TextView(Context);
Button(Context);
EditText(Context);
so my assumption here is that "Context = Activity = Screen" and that "View = Button = TextView = EditText"
so in this example
public Example extends Activity{
onCreate(){
Button buttonObj = new Button(this):
}
}
Button buttonObj = new Button(this);
"this keyword" here is refering to the Example class which extends Activity. Is this code here basically says "put this Button which is View inside the Context which is Activity which is the Screen"?
If I am right then why Activity passed inside Button? because it makes sense if button is passed inside Activity.
5th question what happen here?
add.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
//code here
}
});
What is new View.onclickListener() ?? is this a static method that returns an object who implements onClickListener??
Can you also suggest good books in learning android?
Bundle ~ a Bundle is a collection of data. When an Activity starts (via onCreate), the Android OS (or you!) can pass off some extra data to this activity via this bundle. Do you know what a HashMap is? A bundle is a glorified hashmap in that supports multiple different types.
OnCreate Bundle ~ This bundle comes from Android. Honestly, don't worry about it too much. If you want to start one activity from another, you use an intent (do you know this yet?). As such, you can "bundle" data into the intent (using the setExtra methods). This data from the intent will be included in this onCreate bundle, and you can access it through there.
Context ~ your running application and anything associated with it. When you run your application, everything associated with your application is referenced by this context. All of you activities, views, resources, EVERYTHING is associated with the context. Think of it as the word defines: It is the context of your application. Every application has a unique context.
View ~ A view is anything that can be drawn on screen.
OnCreate():
The entire lifetime of an activity happens between the first call
to onCreate() through to a single final call to onDestroy().
An activity does all its initial setup of "global" state in
onCreate(), and releases all remaining resources in
onDestroy(). For example, if it has a thread running in the
background to download data from the network, it may create
that thread in onCreate() and then stop the thread in
onDestroy().
OnCreate method is called when the activity is first
created. This is where you
should do all of your normal
static set up — create views,
bind data to lists, and so on.
This method is passed a Bundle
object containing the activity's
previous state, if that state was
captured.
Views:
The visual content of the window is provided by a hierarchy of views — objects derived from the base View class.
Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place.
For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views(Widgets) that you can use — including buttons, text fields, scroll bars, menu items,check boxes, and more.
I would suggest that you look at some text based tutorials rather than video as it will be easier to look at things and reread when you are confused.
I'll get started to help you with figuring out what these terms means.
Bundle - not super important for you to understand. When an activity is called, you can add things to your bundle to be sent to the next activity so that the new activity has the information you want.
Context - each activity has its own context and its important to have a basic understanding of it. Your first applications will have one activity (or class) from which everything is done. In this case you only have to worry about the "this" context which means the current active activity. But if you use an application with multiple activities, some may be active and others not. The context tells your app which of the activities is requesting an action, such as showing text or an image on the screen.
Views are your basic UI elements. They can be simple like TextViews (just shows text), Buttons, or more complex like a layout which organizes the other views.
For your example :
public Example extends Activity{
onCreate(){
Button buttonObj = new Button(this):
}
}
Example is the name of your class which uses the Activity resources.
When the activity "Example" is started it calls the onCreate method first.
It then creates a button object that you can "attach" to a physical button found in your layout file.
The setOnClickListener method is used to ready your activity for a button click. The code that goes into the onClick section is what will happen if the user clicks the button.
If you want to get into android programming, you really should first read the FAQ on this site. You should only be posting answerable questions not asking for opinions such as what's a good book. Hundreds of people have already asked that question and if you can't do a simple google search, you might want to wait on learning to program.
But I"m nice so here are some online tutorials that will get you started and explain some of the things you are confused about:
http://developer.android.com/guide/index.html
http://www.codeproject.com/Articles/102065/Android-A-beginner-s-guide

Android: Reusing same View object in different Activities (the case is about ad banners)

I want to reuse the same view object (not the view class, or the xml file, I mean the object in the memory) in different Activities.
I almost had this done. The thing is, of course, the context.
I tried with the application context. It almost worked, but then when I click on the view I am transmitting between different activities, and try to start another application from it (or link) it crashed. (I don't remember the exact crash, but I'll dig it, if you need it).
I tried with some activity, that I didn't mind leaking once, and giving it as a Context. It worked, actually everything worked, until I began to get weird exceptions in ViewFlipper.
My question is, is this reusing really possible, and how to do it stable? Have you got any experience with that?
Thanks A LOT in advance,
Dan
I'm keeping in mind that you can afford to leak 1 activity, as this is the only solution I know:
Declare a static view, say myAdView in your 1st activity (in which you are requesting ad). Now you can ad and remove this myAdView in every activity transation. Ofcource you will have to maintain seperate LinearLayouts for ur ads in seperate activities, where we will add/remove the myAdView
eg. Suppose you are going from activity A to B, then in A's onPause remove myAdView:
private LinearLayout layoutAd;
layoutAd = (LinearLayout) findViewById(R.id.layout_ad); // from A's xml
protected void onPause() {
super.onPause();
layoutAd.removeView(FirstActivity.adBannerView);
}
and in B's onResume add the same (FirstActivity's) myAdView:
private LinearLayout layoutAd;
layoutAd = (LinearLayout) findViewById(R.id.layout_ad); // from B's xml
protected void onResume() {
super.onResume();
layoutAd.addView(FirstActivity.adBannerView);
}
Hope this solves your problem to some extent.
Why don't you use Fragments?
http://developer.android.com/guide/topics/fundamentals/fragments.html
I think your use case is perfect for this.
This isn't really possible in the form you are asking. The views in an activity must be inflated at load time, copying/referencing them in-memory is unlikely to work how you want it to.
Instead, you should look to building the view in each activity you need it, and transferring just the data you need to populate it instead.
If you are trying to improve the performance of your app, I would recommend looking for ways to simplify your view, rather than violating the activity lifecycle.
Update:
Since you've revealed the purpose behind this question (intercepting served ads from a third-party library), I suggest you first contact the company and check the terms of use. If they permit the use of their service while bypassing the View code, then they might be able to provide you with a lower-level API for displaying the ads as you see fit.
If such use is not permitted, consider the fact that they might block your account (and withhold payment) for mis-use.
If you still want to go ahead: DON'T hack away at the Android UI patterns to make this work. Extract the ad images from the third-party library server-side (i.e. building a simple hosted Java webapp with cache store and a REST API) and serve the ads to your Android app from this "man-in-the middle" service. I certainly do not endorse this method, however.
I accept you are seeking some penultimate technical solution for your approach, but I genuinely think it is the approach itself that is the problem here. If I was in your position, I would start to look for other Ad serving solutions that better fit my requirements, as well as contacting the third-party to see if I can pay for more customised integration. Anything involving transferring inflated Views between activities is doomed to constant maintenance problems, if it works at all.
I'm in the same case as Danail. The thing is not about to hack de Ad provider, but that if you want to show a banner through different activities it's a best practice in advertising not to reload it every time you change the activity, because you do more impressions so you CTR (Click Through Ratio) will decrease. You'd rather reload the banner at the time rate you fix, independently of activity changes.
I think the right way to do that would be, as NeTeInStEiN says, using fragments. You could have a unique activity composed by different fragments. In one of the fragments, for example at the bottom, you'd have the banner and you'd load it actually once. Then on the bigger area on the top (let's say we are on a handset) you'd place different fragments, one at a time, that would correspond to your existing activities. When you'd normally "change" the activity, now you'd just change the "main" fragment, but the banner fragment will stay there unchanged.
The main and BIG problem about this approach is that you need to design you app this way from the beginning, because changing the app model from several activities to one activity with several fragments is quite a big code change... :.(
So I understand that, for implementation costs, one could try to "carry" the view from one activity to another. But as I saw in other responses, it's really not recommended and a troublesome way...
If you want a variable to be used within multiple activities then best practice for it is to put them in a separate class (can be named as Constants or MyVars) as static variable and use them in any activity you want as like Constants.SavedVar or MyVars.SavedVar as below is code example.
public class MyStaticVars {
public static Context myContext;
}
// First Activity where you want to save a specific context
MyStaticVars.myContext = ContextToBeSaved;
// Any Other Activity where you want to reuse that context
priviousContext = MyStaticVars.myContext;

Categories

Resources