Android Tabs and global variables - android

I am using android TabWidget and I have one main activity where I am managing all the tabs.
Each tab has his own activity:
private void setTabs()
{
addTab("News", NewsActivity.class);
addTab("Project", ProjectActivity.class);
addTab("About", AboutActivity.class);
addTab("Contact", ContactActivity.class);
}
The data for each tab is downloaded from the server in JSON format. My goal is to download all the data on the oppening of the application and then to use it for each tab (activity).
Is there a possibility to share those variables from the main activity to the others where I am managing the tabs? I know about using the Intent class but may be there is another easier solution with the tabs.
Thank you very much.

Declare static variables in your main activity and store the data in them.
For example, public static integer myInt;
myInt = ...;
Now when you go to the other Activities, just use MainActivity.myInt to access its value and even update it if you want. No need to pass the variable around using intents.

You can create a class that would hold any variables or objects that you might want to use throughout the whole app.
public class myClass {
private static int myInt;
public static void setMyInt(int i)
{
myInt = i;
}
public static int getMyInt()
{
return myInt;
}
}
Then you can set any variable from anywhere and use it anywhere.
myClass.setMyInt(10);
int i = myClass.getMyInt();

You may want to create your class MyAppication extends Application (you will also have to add it into Manifest). This MyApplication class will exist all the time your app is running so you can store things in there.

I think it would be better to use fragments for your purpose..
You have the main activity which has the tabhost/tabwidget and a layout to display a fragment for each..
Based on the currently selected tab you display the corresponding fragment in the layout.
This way your main activity can have whatever variables data your fragments need to use.
All the fragments are able to access the data in the activity they are displayed in, just make sure to create getters and setters

Related

share argument between all fragments

I am making a bottom navigation app and want to share data between all fragments, for example clicking a button to share a name for all action bars. With safeArgs I can only send data to one fragment.
And I want to ask, is any solutions for global arguments(global variables) like redux in react native or provider in flutter?
Thank you
You can use shareviewmodel, it's best practice
Link refer: viewmodel
EDITED
Just create a public variable as a class variable in your MainActivity
public class MainActivity extends AppCompatActivity{
public int myVar; // outside of all methods
...
Then you have access it everywhere in your Fragments inside that MainActivity, like this:
MainActivity mainActivity = ((MainActivity) getActivity());
if (mainActivity != null)
mainActivity.myVar = 15;

Android, should all code be written in an Activity

I am more familiar with iOS development than Android and I am wondering if all code should be written in an Activity rather than having a "model" class.
I have a couple screens each with a few checkboxes and I want them all to behave the same on click, I am trying to figure out how I would do this without writing repeating code in each activity. Thanks!
No you should not. If you are familiar with java, think of an activity as a extension of main with OO added.
In your particular example you can create a class with a method like:
<MethodName>(View <checkboxClickedName>){ //your code here }. and then add this to the checkbox in the XML android:onClick="<MethodName>", you may need the full package path (e.g. com.example.app.)
Note: if some of the commands/objects you need are only available within an activity you should create this in an calss that extends Activity or preferably within the running activity.
You could have a base class that extends activity that contains the methods that you want executed on click (either implemented or abstract). Use this new base class instead of activity when making new activities. In the layout xml, you can set the onclick of each checkbox to be the method in the base activity you want executed.
The best practice would be to use a single activity and switch fragments as if they were your screens. Then, the activity could simply implement the listener interface that the fragments would re-use.
Since you have multiple activities this becomes a little bit harder. To really re-use a single listener, I can think of a single (not so beautiful) option. Create a static listener and lazy load it:
public class MainActivity extends Activity {
private static View.OnClickListener sCheckboxClickListener;
public static View.OnClickListener getCheckboxClickListener() {
if (sCheckboxClickListener == null) {
sCheckboxClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Work with v
}
};
}
return sCheckboxClickListener;
}
}
And in each of your activities call:
findViewById(R.id.checkbox1)
.setOnClickListener(MainActivity.getCheckboxClickListener());

Changing text from another activity

How to dynamically change the content of a TextView from another part of the screen?
I have a TabActivity class that draws a RelativeLayout that contains a TextView followed by a with several tabs. Within each tab is a separate Intent. From one of the tab intents, I would like to change the text (via .setText) of the TextView from the parent TabActvity.
Is this possible?
You should use Android Architecture Components :
You can create a ViewModel containing LiveData of your data object (LiveData<String> in case you want to change only text).
When you will change your live data object from one Activity or Fragment all other Activities and Fragments observing for this live data object will get notified.
Official API doc has complete example with description.
Make a public method in your TabActivity that sets the TextView's text, then call getParent() from the child activity, cast it to your TabActivity class, then call that public method.
You could try implementing a handler for the parent Tab which does the job. Pass the text in a message object from each of your respective tabs. To be safe, make changes within the handler inside a runOnUI block
In a case of changing text from asynctask file, you need to implement an interface with a listener. Example:
AsynctaskFile:
OnReadyListener onReadyListener;
public class ABCAsynctaskFile{
...
onReadyListener.onReady();
}
public interface OnReadyListener{
void onReady();
}
public void setOnReadyListener(OnReadyListener onReadyListener){
this.onReadyListener = onReadyListener;
}
ActivityFile:
public class ABC extends AppCompactActivity implements ABCAsynctaskFile.OnReadyListener{
..
ABCAsynctaskFile aBCAsynctaskFileObj = new ABCAsynctaskFile(context);
aBCAsynctaskFile.setOnReadyListener(ABC.this)
}
#Override
public void onReady(){
// Your wished changed in edit text.
}
This structure will help you to prevent null pointer exception.

Can I update a list view in one activity while im in another activity?

I currently have a tab layout with 2 tabs, one tab with a list view and one with the option make strings so I can add them in the list view. Both tabs have their own activity because this made the code much more structured, and I dont have to repeat my self later.
Lets say im in the tab that offer me to create an string, and i press the update list button, how do I update the list view without startActivity()? If i use startActivity(), it starts List.java, and instead of displaying the list in the list view tab, it takes full screen, which defies the purpose of the tab view. In other words, the startActivity() steals the focus from the tab view of the list, and sends it fulscreen.
Thanks for your time.
Edit: I want to update the activity in my list view tab, without starting a new activity that goes to fullscreen, and doesnt update the one in the tab.
One solution is to have your data model separate from your view (Activity), this is good practice in general, but in this case allows your two tabs to interact with the same model.
You could provide access to the data model in your Application class. Then, when onResume is called on your list activity you can update the view based on the current data.
edit:
public class MyApplication extends Application {
private List<MyObject> myData;
public List<MyObject> getMyData() {
return myData;
}
public void setMyData(List<MyObject> mydata) {
this.myData = myData;
}
}
In your manifest you need to add the application tag to specify that it should use MyApplication as the application class.
Then, in your activity:
public void onResume() {
MyApplication app = (MyApplication) getApplication();
List<MyData> data = app.getMyData();
// update my view with the data
}
I had the same problem when i was making my app and the only solution i found was to add this flag to my intent so every time i go to the tab it would refresh it self
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
I hope it helps.

How to use intent between tabs in java/Android?

I would need to know how to handle the intent between tabs. For example, I have a tab activity with two tabs. First on content is a text view. another one is a map view. When i click that text view it redirects to the tab2. it can be easily achieved by setCurrentTab(1) or setCurrentTabByTag("tab2") methods. But i want to pass lat and long values to that Map Activity to drop pin. What is the better way to use intents or getter/setter in java? What do you prefer? if your answer is "Intents". How?
A interesting problem. I understand it that you want to change to the second tab on a click in the first tabview but also pass special data to the second tab that is dependent on the action in the first tab.
I would generally start your views inside the tabs with an activity. However this is done at the moment the tab host is configured. That means both intents the one for the activity that lets the user choose lat long and the one that shows lat long are openend at the same time.
Therefore you can't add the information to the intent used to intialize the tab host.
I don't like the solution but the only thing that comes to my mind (using different activities for the tabs) is using a custom application that stores a reference to an object containing the data that you need to update the view in the second tab. You have to extend application with an own class and add this class in you manifest, now you can call getApplication in the first tab cast it to your application class set lat and long just before you call setCurrentTab. In the second tab you can call getApplication() again and you will then get the application object that is the same for every activity at every moment of your app running. You then have cast it again to your application object and retrieve lat and long value. See this page in the google refs on how to use a custom application class.
To use a custom application class add the following to your application tag in your manifest:
<application
...
android:name=".somepackage.CustomAppClass"
This will tell Android to instantiate the CustomAppClass as your Application class at the moment your app starts. You need to extend Application to avoid errors on start up.
Another solution but not the one I would prefer is to initialize the views yourself and initialize the tabhost with views and not activities. With a map view in one of the tabs this could be very memory heavy.
If you want to pass values between activities, I suggest looking at
http://developer.android.com/reference/android/content/SharedPreferences.html
the best way to get values from one itent to another.
With sharedPrefrences, there is only one instance of the class for the whole application, which means that you can store values in the files, switch intents or activities, and then recall those sharedPrefrence files that have the data in them.
The only downside is that you have to pass primitive types (int, string, boolean) but I'm sure you'll figure ways around this :).
I dont see the Problem here:
Maybe its a little bit of hackish but following Code works for me:
public boolean onClick(View v) {
//get your data you wanna send.
//If it is an Object it would be good if it is Parcelable
Object o = getYourData();
// or Parcelable p = getYourData
Activity activity = getParent();
//I'm assuming were inside an Activity which is started by TabActivity
if (activity instanceof TabActivity){
TabActivity ta = (TabActivity)activity;
//now determine the Tab you wanna start
ta.getTabHost().setCurrentTabByTag("yourTag");
//or ta.getTabHost().setCurrentTab(yourID);
Activity current = ta.getCurrentActivity();
//check if the Activity is the one you wanna start
if (current instanceof YOUR_ACTIVITY_YOU_WANNA_START){
//Cast to your Activity
YOUR_ACTIVITY_YOU_WANNA_START yourActivity =
(YOUR_ACTIVITY_YOU_WANNA_START)current;
// you only need to put Data inside your Intent
Intent intent = new Intent();
intent.putExtra("EXTRA_DATA_TAG", o);
//your Activity must Override onNewIntent and make it public,
//or simply add another method
//with whatever You like as parameter
yourActivity.onNewIntent(intent);
return true;
}
}
return false;
}
this way you don't have to mess with Application, SharedPrefs or other unnessesary stuff mentioned here
If you make the intent you are using to start the second tab activity a global intent.
You can then add extra's to this intent in the onPause() of the first tab. Note: you have to define all your tabs in separate activitys than your tabhost TabActivity as this activity's onPause() is never called.
This also help's with the answer above, if you are using a global variable saved in your activity that extends application, you can set this in the onPause() as it is fired before the activity is switched, which you might find an issue if setting this elsewhere

Categories

Resources