I'm currently writing an app to provide food information/a grocery list function. My current code uses a switch statement to determine which button (fruit, vegetables, etc.) was pressed and passes an array list to a fragment that is then displayed as a listview.
When its called by the information activity, users can click on items and be presented with a detail view. If the calling activity is the grocery list activity, users can swipe to add to an empty array list. Since the bulk of the code used is the same, is there a way to do this without using two separate fragments?
All I can think of is putting the activity hashcode in the bundle being passed
to the fragment and using if statements to determine which activity passed the bundle (and thus which event listeners are used), but this doesn't seem like a very good solution to me.
Related
I have general questions about BottomNavigationView. I would like to have a BottomNavigationView in each of my Activities in an App for ordering something (e.g. food). It should have 4 buttoms:
Back
Info
Stats
My Orders
With 'Back' the app should just go back to the previous activity. The buttoms 'Stats' and 'My Orders' should switch to a persistent activity that should not be destroyed when not being displayed. 'My Orders' should display the last orders. The buttom 'Info' should only display some information about the current item or current menu (depending from which activity it is called). So basically I have 2 questions:
Should the Activities 'Info', 'Stats', and 'My Orders' be real Activities or just Fragments? Normally I think that at leat 'Stats', and 'My Orders' should be real Activities as they are persistent. But in many BottomNavigationView only Fragments are used?
How can I pass content information to the Activity/Fragment 'Info'. This Activity/Fragment should display information based on the Activity is was called from. Let's say the Activities are different dishes. Do I have to create a separate Info-Activity/Fragment for each dish? Or can I somehow define a dynamic Activity/Fragment that displayes information based on the current Activity?
I'd appreciate every comment and I'd really appreciate your help.
The recommended approach is Single Activity and Multiple fragments.
You can do this using Jetpack's Navigation Component
In case you need to pass data from an Activity/Fragment to the new calling Fragment, it can be done by setting arguments on the calling fragment and then getting it on the called fragment. If there is something which requires to be dynamic, for example- dishes fragment, make a single fragment and common layout and load the data dynamically from the backend.
For Setting Arguments, this should help
How to pass a variable from Activity to Fragment, and pass it back?
Note: You can use fragment without using Navigation Components but you have to use FragmentManager and FragmentTransaction and also have to maintain the Backstack by yourself which could be quite complicated
Is it possible to change something in a view depending on the sequence of activities? For example, in an adapter I would like to highlight a text, corresponding to an element clicked in a list of elements of a previous activity. But this, only if this adapter is the result of a sequence of certain activities, given that it is used in a fragment, hosted by an activity that can in turn be called up by one of two other activities.
You can keep history of every activity opened by keeping a list/stack of ids (integer or string). First activity that starts in your app will make a new empty list and record itself into it. When another activity is opened you pass that list in the intent. Next Activity extracts the list and adds its own id in it then passes it to next Activity in intent. This way, any activity will have a history of all activities opened previously.
If you want to send additional information along with ids you can make a Parcelable class and pass that along.
Let's say I have two activities/classes. MainActivity and SecondActivity. For each of these activities I have individual XML files. In SecondActivity, I have a ListView with ID listview.
How can I retreive the ListView from SecondActivity in MainActivity?
I tried just plain and simple (in MainActivity.java):
ListView listview = (ListView) findViewById(R.id.listview);
But that crashes my app when I try to set an adapter on it (nullPointerException). I tried placing it directly inside my class, and inside the onCreate method. Both causes a crash.
The line that causes the crash looks like this:
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList);
listview.setAdapter(adapter); //crash (nullpointerexception pointing to nullobject)
What I want to do is get that ListView and use the "listview" object to add elements to the listview in my MainActivity.
In Android (with exceptions) you cannot have more than one activity running at the same time. You can have multiple Fragments, but a single activity is shown at a single time (ok, this is not 100% true anymore, but for all intents and purposes, this is still the case).
What you're trying to do is considered extremely bad practice in Android (and iOS for what is worth).
What can/should you do?
Your requirements appear to be some form of: I have a list of items, and I also have another activity where I want to add or remove things from said list.
This is fine, but you don't need "two activities" to do this.
Have one activity to show the list, and when you want to add the contents, either launch another activity to show the UI of the "edit/add" or use Fragments (one Fragment would have the list, the other would have the UI to edit the list).
Where is the data in all this?
Stored in a THIRD place (let's call it "YourListRepository"), which is a class where:
From the "List" you'd simply say: Repository, give me the latest list!
From the "Edit" screen, you'd say: Repository, give me the item "N" from the list. And then, you'd say: Repository, here's the updated item "N", refresh it.
Going back to 1 (to display the updated list) is automatic, since it asks "for the latest list".
Where to learn more?
Given the tenure of the question you posted, it appears that you're relatively new to Android development, and therefore I suggest you spend an hour of your time, reading Application Fundamentals from the official Google documentation.
I have a Fragment A (say) which contains a FragmentPagerAdaptor, which further contains Fragments (having list view).
When I click on a list item, I replace the complete Fragment A with another fragment (say B), I have also added the transaction for Fragment A in the back stack; now when I press the back button from B, the list in the child Fragment of A gets recreated and scrolled to top.
I want to retain the state(scroll) of the list, I tried storing the scrollY of the list and setting it again, but it's inaccurate and the list takes some time to initialize, also it takes time to scroll (since the list can have thousands of items).
I came across this link to resolve the issue:
http://ideaventure.blogspot.in/2014/10/nested-retained-fragment-lost-state.html
but setting the setRetainInstance(true) in child Fragments crashes the app saying:
java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
It is also a known bug in google forums:
https://code.google.com/p/android/issues/detail?id=74222
Any kind of help will be greatly appreciated!
I want to retain the state(scroll) of the list, i have tried storing the scrollY of the list and setting it again, but it's inaccurate and the list takes some time to initialize, also it takes time to scroll(since the list can have thousands of items).
this is the recomended aproach, retained fragments were designed to maintain data not UI elements, also nested fragments have some limitations. There are SO's on how to maintain list scroll position, ie.: Maintain/Save/Restore scroll position when returning to a ListView. So you should be able to find a working solution.
If you have some heavy data structure for your list, you can put it inside non nested retained fragment with no UI. This fragment will not be destroyed during config changes (like screen rotation), but it will still be destroyed when you close your app and Android decides to kill your process. So This may cause crashes if you forgot about this case, you must prepare your app for it.
Other option would be to store you list data in sqlite database, it would be immune to config changes, but probably updates of sqlite might be slow.
I'm looking for a method in the Fragment Lifecycle, but I'm not sure which one.
Here's my situation: I've got a Fragment inside a ViewPager. The Fragment displays a List with some information. I fill the list in the Fragment's onCreateView(). When the user opens a different Activity (settings in this case) and changes some settings, the information that the List in the Fragment has to show, changes. When the user returns to the Fragment using the Back-button, the onCreateView() isn't re-called, so the information in the List isn't updated.
My question is: The onCreateView()-method isn't called when the user returns to the fragment form a different Activity, but which method is called here? I need to know this because then I can fill the List in that method.
Thanks in advance!
Important and non-obvious point it that Fragment's onCreateView() being called not only in case you selected Tab with this Fragment. So don't rely on onCreateView() of Fragment when using ViewPager(). When You select the Tab, Android creates sible views (caches them) or makes something similar.
You should call your update method when user selects proper Tab in ViewPager (don't remember exactly, but hope it helps).
onResume() is the simple answer, called when user comes back. for more details refer lifecycle here FragmentLifecycle