Fragment Implementation - android

I am new to Android Coding so this might seems to be simple, but please help me solve my confusion about Fragment:
Can a fragment "do stuff" like Activities (like call some methods, run some
schedule task. Or it is more like a view to display the info given by the parent Activity
Can 2 fragments run at the same time, for example, if I have 1 fragment runs a scheduled task every 10 ms and 1 fragment runs another scheduled task every 20 ms, can they run together?
I use FragmentPagerAdapter to create different tabs, each of the tabs holds 1 fragment, will switching between tabs pause or stop my fragment? Can I switch to tab 2 and make the fragment on tab 1 still running?
How can a Fragment communicate with other Fragment (with same parent Activity), for example fragment 2 get sensor information and if it is larger than some threshold it flags fragment 1 to do some thing?
Please enlighten me, thank you very much

You can think of Fragments like sub activities. They can almost do everything that activities can. They just extend Fragment, so the code might be a little different. They can have all the views that an activity has.
For your scheduling part, you will have to switch the fragments (so this cant happen in the background), but if you want to switch while the app is on, it is possible.
For the third point, look at the image I have attached(fragment lifecycle)
And this is about communicating with other fragments.

Related

How to model cross fragment transaction (ongoing process) in Android MVVM application?

I am developing an app that has some ongoing process that almost all screens depend on.
Let's call it ActiveTransaction. So, one fragment prepares items, the other fragment prepares payment, another adds discounts, etc... If one part fails, everything needs to rollback.
So, basically, I need to achieve atomicity across multiple fragments. I've tried to use shared ViewModel for this, but since each fragment adds its own stuff, that shared ViewModel has become too big.
So, I wonder what would be the best way to handle those processes that stretch over multiple fragments.
Should I have perhaps a singleton object ActiveTransaction that is injected in each viewModel?
Is this maybe what other technologies call the app State?
I haven't found anything in the MVVM architecture guidelines.
You can create Tabbed Activity - blank Activity with tabs. New project -> Tabbed Activity.
You will have one activity and multiple fragments.
So all functionality will be in MainActivity. Your fragments will contain views, which will call methods from MainActivity. All objects and calculations will be in main activity, so if it fails (because of memory lack), everything will collapse too.
For Example:
You have one Tabbed activity MainActivity and 3 fragments: Item Fragment, PaymentFragment and DiscountFragment. MainActivity contains multiple methods, let's say prepareItems(), preparePayment(), addDiscount(). User can go through Tabs, opening fragments. MainActivity methods can be called only via fragments. So if MainActivity collapses, the whole process will collapse.
So you will achieve atomicity and user can see changes by going through tabs. You can replace Tabs Activity by other scenario with single activity and multiple fragments which don't have functionality but contain views which will call methods from MainActivity

Fragment/Activity Best Practice

I set up my application in the following way and am curious if it's considered "best practice." I have two activities and two fragments. Activity 1 launches and immediately uses Fragment 1 to display a RecyclerView of items. An Item is clicked in the Fragment, it's communicated back to the Activity through an interface, some logic occurs and Activity 2 is launched, which immediately uses Fragment 2 to display the detail of the selected item.
I did this because A)I like the logical flow of Activities within an application and 2) I needed to create tablet layouts in which I could use both the Fragments to fill the screen.
The more I'm looking at this thing, I'm thinking why not simply have 1 Activity that manages both of these Fragments? Activity 1 launches Fragment 1, item is clicked, info goes back to Activity, FragmentManager replaces Fragment 1 with Fragment 2.
My question does one of these ways adhere more to "best practices" or are they both fine and it's a matter of choice?
You've not described your problem clear enough to use more than one Activity, other than unrelated data to the list and what happens when you click there.
What you described is a "master-detail" flow, and that is a good use case for one Activity and two (or more) Fragments - a list + some detail page. This especially makes sense on larger screens when you can show those Fragments side-by-side.
For example, you can have an Activity that holds a navigation screen (whether that be tabs, a drawer, or a bottom view), then everything you navigate to within there is a Fragment.
Otherwise, you redirect to some "settings" page, for example, that is a new Activity, which demonstrates the "Single responsibility principle" in your UI.
Well you can go with the single activity - multiple fragments. You can pass data between fragments using bundle as well. Matter of choice also depends on the use case. But fragments are made to use as light weight activity that requires less resources then activity. Most of the things are possible with fragments. So unless it is not required to use activity my choice goes with single activity - multiple fragments.

Android espresso test multiple fragments consecutively, inside the same activity

I have a fragment initially inside my activity, this fragment contains a button that's when it's clicked it open the second fragment, and the second fragment contains a button that's when it's clicked it open the third fragment, and so on ...
Now I want to test the launch of the third fragment after passing by the 2 old fragment (not testing the fragment in isolation), I tried to preform a click in the button inside each fragment but it seems espresso doesn't wait for the 2 fragment to launch, before clicking the button inside it, is there any solution for this ?
Without seeing the code its hard to tell what the best way to handle this would be.
However this seems like an issue with the IdlingResource. Espresso should wait until 2nd fragment has finished launching before moving forward.
You can handle it by adding a SystemClock.sleep(int milliseconds) . That is not an ideal solution however and sleeps should be avoided at all costs.
No it's not a timing issue I have an Activity with 3 fragments all of which are visible concurrently. Android Espresso will only do tests in the top fragment and refuses to acknowledge the presence of all the rest of the fragments.

Upgrade/Migrate from Multiple Activity Intents to Single ViewPager & Fragments

I used to have 3 activities with 3 layouts.
1. HomeActivity.java (activity_home.xml)
2. HelpActivity.java (activity_help.xml)
3. SettingsActivity.java (activity_settings.xml)
Whenever i had to open other activities, i used animated slide-in-out intents using overridePendingIntent. In this way, all the variables of HomeActivity stayed in itself and HelpActivity's variables/methods were in itself and same for SettingsActivity. I used onCreate() in these to perform some activity specific code. and, android:onClick="fetchSarcasm" from activity_home.xml was calling specified method in HomeActivity.java. So, there were no conflicts. All the normal things, that happen in an AndroidProject with 3 activities and used intents to switch to one another, were happening as i wanted.
But now, I wanted to migrate to ViewPager instead of slide-in-out intent transitions. In this way, there will be only one Activity with an XML of ViewPager. This ViewPager and its FragmentPagerAdapter gets the Pages from 3 classes extending Fragment with relative XML layouts.
I want to ask: Where do i write my Page Specific Code for onCreate(), layoutView's onClick="" and for onChangeListeners. Because, 3 classes extending Fragment do not have any Context or findViewById() and they do not respond to android:onClick="method" in different layouts.
Do i need to mix all that code of three activities into one containing ViewPager? If so, this makes ViewPager activity pretty heavy. and, writing if(page=2){ dothis(); } seems absurd for all pages at every code point. Any checkbox(view) that is in page 3, becomes null in other pages.
I know this might be a stupid question. I have spent almost 4 days trying to achieve something but i can't. Also, this is just my 2nd month in android, so i am new. I do not use Action Bars, Tabbed Bars or Navigation Drawers.
I am available on SO Chat too if you want to ask something more.
I just want to know how do i merge all the work i did when I was not using ViewPager.
If you're only reading the Preferences once for each Fragment, you can move your previous Activity.onCreate() logic to each Fragments onViewCreated() or onCreateView(). Read your shared Preferences there and set your Checkboxes accordingly.
Fragments inside a ViewPager aren't necessarily recreated on each page change. You can change how many Fragments are instantiated at a time with ViewPager.setOffscreenPageLimit(int).
Fragment Lifecycles explained

Why is my fragment onCreate being called extensively whenever I page through my applications viewPager?

I'm not quite understanding this fragment lifecycle business.
I have a pretty standard 3 page horizontal slider view Pager layout for a "view details" section of my app. I start my app on the middle page of the three. My FragmentActivity sets the page to page 1.
mPager.setCurrentItem(1); //default to center page, current data view fragment
I've been using the FragmentStatePagerAdapter because using the FragmentPagerAdapter crashed my app at times, when coming back from a suspended state for example, and this was the quickest way to work around that for now. Seems to work but I suspect the State aspect is what might be the cause of my problem here, maybe.
So at first I thought that I would have each fragment do the work of getting data from a rest service and then showing it in a list, but I'm not so sure any more.
I tried running a unique async task to fetch data in each of the fragments onCreateView events.
Then after reading more on the fragment lifecycle I switched to onCreate, having noticed that the onCreateView was being called quite heavily, which in turn made for a greedy app that too often requested data over the wire.
Switching to onCreate hasn't changed anything. OnCreate is still geting called just as much as onCreateView for the 2 adjacent fragments.
The odd thing is that the fragment that I set to be the first one to display in Fragment Activity only gets the onCreate called the one time.
Something doesn't feel right here.
Right now I'm thinking that I should have the parent fragment activity declare and call all the async tasks to fetch the data that I need to display in the fragments.
Set the results of the async calls in an object owned by the parent fragment activity and then have the fragments use the object contained by the parent to create the list view etc.
But what if the async tasks started by the parent activity don't finish before each fragments onCreateView is called and the object contained by the parent isn't ready yet.....
signed, confused and frustrated
ViewPager is quite zealous in shutting down things it isn't currently using, and this is exactly what is happening here. The default behaviour is for ViewPager to "keep around" one page either side of the page being viewed, and destroy the rest. Hence in your 3-page view, page 3 gets destroyed when selecting page 1, then when page 2 is reselected page 3 is recreated. As you've noticed, page 2 only has onCreate(..) called once because it is always adjacent to, or is, the currently selected page.
To solve this, simply set ViewPager.setOffscreenPageLimit(2). Then the ViewPager will keep all your Fragments. Obviously this isn't a good idea for a large number of Fragments, but for your case it should be fine.
#Espiandev's solution will work for your current case, but you're right that your state is the issue. You should use the setArgument and/or onSaveInstanceState methods to save your Fragment's state (which shouldn't be too hard, since e.g., a response from the server can usually be represented as a String), and then use getArgument and/or the Bundle passed in onCreate to restore it.
Alternatively, you could have your Activity do the server fetches, and then call setArgument for each of your fragments, and check the arguments inside your Fragment to determine if your data has arrived yet (and if not, potentially display a loading state of some kind).
If you care at all about screen orientation change, this related question will also be useful to you.

Categories

Resources