Intents or directly accessing a public variable of a different class - android

I noticed that most programmers in Android use an Intent or broadcast receiver to send a short text message from one class to another class.
If I am using a utility class that does not extend any other class like Activity or Service, why not just directly access the variable in the utility class like this.
UtilityClass utility = new UtilityClass();
String gotIt = utility.theOtherVariable; // direct access to variable in other class
is there anything wrong with doing it this way? I would rather do this than use an intent or broadcast receiver to send the small text message from the utility class to the Activity class.
EDIT
in addition to the instance of the class, you can also make the variable static that your are passing from one activity to another. in either case I don't see any value to using an extra of intent or broadcast receiver to pass information from one Activity to another.

Yes of-course you can use that And even it is good practice that you are using your own data structure but it is depend on need and scenario.
For example suppose you are receiving data from gps and you need that data in your app at some 5-6 places then its good to design one class and store the gps data in the variable of the class and access it where ever you want in your ways

Yes of course its good thing to make public class and keep your where Variable and Function as publicly so you can use in further activity.But that you all ready know that this type of function and variable will be use in some activity.
Where Intent is like Good and easy way to switching data one activity to anther activity.like if you don't want to use some variable more then single next activity then it will useful. More Impotent use of Intent is Return activity Result. like if you want to perform action but its depend on next activity then Intent will use as powerful tool to achieve your task.
Short and Sweet : It's Depend on Requirement.

Try this,
UtilityClass utility = new UtilityClass();
Initialized Utilityclass in Your Activity.Use Utilityclass object you will get all values in your utliityclass.
Example,
public class UtilityClass{
public static string gotIt = "value";
}
public class MainActivity extends Activity {
UtilityClass utility = new UtilityClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xml);
String str = utility.gotIt;
}

Related

Moving data back and forth between two open activities

I have two activities- act1 and act2. I want to transfer a String from act1 to act2 when the user presses a button and after some computation I want to transfer a LatLng from act2 to act1, while keeping both activities open (or at least be able to restore every change in act2 from the app start).
Things I tried:
I saw here that if I add some flags to the intent I won't start new activities when using startActivity(). It works well getting from act1 to act2 but after starting act1 from act2 it stops act2, so in the next act2 opening it will make a new act2 copy.
I looked at the not-deprecated version of startActivityForResult, but since I need both of the activities open it's not what I want. I also want both of them to receive and return data.
From here, using static data structure in one activity may not be good practice.
I tried using extras and onNewIntent but couldn't make it work (since I can't keep both activities running).
Background (if relevant):
I have an app with two activities- main, which stores a ListView, and a map activity.
The map must have a marker placed in each saved address.
The list has two button types:
"Add a new place...", that open the map activity, and adds a new marker where the user wants.
-some address-, that open the map in the location corresponding to this address.
I need a way to pass the desired address to the map so it'll show this location, and I also need to pass the new saved address back to the main activity after creating a location.
You can use the repository pattern to store the data in a way accessible by all code in your app.
What is a repository?
A repository is a simple class that holds some data and provides access to it. Something like:
class Repository {
private String theString = "";
public void setTheString(String newValue) {
theString = newValue;
}
public String getTheString( {
return theString;
}
}
It's a good idea to give a more descriptive name to the repository. So if this is a repository that stores location data, you could name it LocationRepository.
Where should it be created?
A good place to keep the reference to it is the Application class. If you don't have one, you can define it like this:
class MyApplication extends Application {
private Repository repository = new Repository();
public Repository getRepository() {
return repository;
}
}
It needs to extend the Application class provided by the android framework
You can also override the onCreate() method for more complex initialization, if necessary in your case
Define the application class in the manifest
In order for the android framework to know about your custom Application class you need to define it in the AndroidManifest.xml:
<application
android:name=".MyApplication"
...
Access the repository in your activities
Now in each activity you can cast the application context into your application class:
class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Repository repository = ((MyApplication) getApplicationContext()).getRepository();
System.out.println(repository.getTheString());
}
}
If you want a cleaner approach, where you care about architecture design:
Create a ViewModel per each activity
Create a Singleton, which the ViewModels access, and use it to share the data.
The Singleton could be something like:
object AddressManager{
fun saveAddress(address: Address) {
}
fun getAddress(): Address{
}
}
And of course, I would advise you to use Dagger and Hilt for the injection and not to use "object", but this is again more and more design ideas.

Can we usually skip using intents by using public variables in Android?

Many times we use intents to send data to a Fragment or get data back from a child. Can't we just put data in a public variable?
For example imagine if we want to get data from user from a dialog box.
I'm just talking about the "possibility". Undoubtedly, It is superior to use intents for code cleanness or safety...
you don't send intent's to fragments, if you want to use objects you need to have your object implement Parcelable then you can just send the object in the intent bundle
public class MyActivity extends Activity {
public int someValue = 1;
}
And in any fragment which has MyActivity as a host you can access ((MyActivity) getActivity()).someValue.
I think what he means is sending (local)broadcast... which is by the way the proper way of doing it according to my understanding.
Of course it is possible to have public (or even protected) fields and access them from a child-fragment with something like this:
assuming your parent activity is named "MainActivity"
((MainActivity) getActivity()).mMyPublicField
or:
((MainActivity) getActivity()).getPublicMethod()
- but I would never recommend doing this!
especially when you also start manipulating the public field you can run into ugly trouble when different threads are in play.
If something needs so be shared across the whole application, use SharedPreferences (if you want to store it for the next app session too) or as I mentioned first LocalBroadCastManager.

Android intent extra message versus static variable

What is the purpose of using an intent with a message instead of just declaring a static variable in java and calling it from the new activity? It seems easier to me this way because you can have the static variable be anything you want (i.e. ArrayList, Object, etc.).
public class FirstActivity extends Activity {
public static String name;
...
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
name = "Robert";
startActivity(intent);
}
public class SecondActivity extends Activity {
...
textView.setText(FirstActivity.name);
}
By using extras to start SecondActivity, you make it more reusable. Many of the stock activities work this way, that's why you can reuse for example the camera activity to take and save photos, because it does not make assumptions about who is calling it.
In your case SecondActivity depends on FirstActivity having been loaded in the JVM. I would not count on that, and it's certainly not a recommended practice to have such dependency between activities. Don't do this. Use extras to pass values between activities, as recommended by the SDK.
To clarify, the OP's strategy won't work if another app outside of his/hers wants to handle the Intent. Because of this, it's not a "best practice".
There are roughly 30 different putExtra variations for an Intent, each representing a different data type you can add. They include general purpose data types such as Bundle, Parcelable, Serializable, and so forth. I can't think offhand of anything that these don't cover.
I don't use statics or variables defined by overriding Application or other similar ways of assuming that some data is floating about in storage. It's much more robust to assume that my Activity or Fragment is totally independent.
Using Intent make you slower than static
For example if you use mvp or mvvm
At least you have to pass like id through layer by later

passing data through activities in background

I am working on database for a game.
I would like to get the score from one activity and call it in database activity, where it will be updated in the database by using intent, the game gets paused when intent is fired.
I have also tried using application class (suggestions on that are welcome).
Is there any way to pass data among activities by firing intent in background so that it does not interrupt the gameplay?
Your database should not be in an Activity. An Activity represents one screen (or one use-case) in your application, and should not represent implementation details like a database-class.
As an alternative, you can put your database code in a Singleton class that can be accessed from everywhere in the same application. You can also create the database in the Application's onCreate method and store it in a static field there or just create a separate class that exposes static methods to access the database.
If you are somehow dead-set on using Intents, you would need to use a database Service instead of an Activity. This way the current Activity will remain on top when you send the data to the service. But that would complicate things a lot compared to a simple static class/singleton approach.
You seem to have a big mix up: There shouldn't be a database activity. You should create a database helper class and make it a member variable in your application class.
// inside application class
private static MyDatabaseHelper mMyDB;
public MyDatabaseHelper static getDatabase() {
if (mMyDB == null) {
// mInstance should be the application instance, means make the
// application class a singleton
mMyDB = new MyDatabaseHelper(mInstance);
// the constructor should open/create the database
}
return mMyDB;
}
With this you can work with your database from everywhere.
With that you can easily update every value from everywhere. So no need to fire an intent to pass values around. Instead just update your database directly.
There are multiple ways to this.
You can use handlers, services, then use setresult which give call back to onactivity result of the parent activity.
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
Bundle b = new Bundle();
b.putInt("key", 1);
intent.putExtras(b);
startActivity(intent);

How can I get a reference to the Activity that called a method?

I have a class that extends AsyncTask to send an ethernet message. When created and called within my MainActivity it works fine:
new SendCommandTask(MainActivity.this).execute(ipAddress, portNum, message);
However, I would like to embed this within a method in a new class instead...
public class NewClass{
String ipAddress;
String portNum;
String command;
public NewClass(String ip, String pn, String, c){
ipAddress = ip;
portNum = pn;
command = c;
}
public send(){
SendCommandTask(MainActivity.this).execute(ipAddress, portNum, command);
}
}
... and call the method directly from my MainActivity:
NewClass newClass = new NewClass;
NewClass.send();
I have tried passing the activity as another parameter in the constructor, but the method pukes when I do that. Is there another way to refer to the calling Activity in my NewClass? Or am I stuck running the AsyncTask from the MainActivity?
(I hope this makes sense, I'm very new to Java and OO programming in general.) Any help is very much appreciated!
Please see this answer that I wrote a couple of days ago. I think it applies here as well. The main additional consideration is, does your AsyncTask need to be able to outlive its calling Activity or not? If there's any chance that the Activity will be closed or restarted, either kill the task in onStop() or be careful not to use any shared fields.
If your AsyncTask is going to directly read any members that are part of the Activity that you are passing in, you may as well just keep it inside the Activity. Factoring out the task into a freestanding class is best done when you want it to be independent and able to work with several Activity classes.
Also, consider doing your work in a Service instead of an Activity. I'm a big fan of IntentService.
You could try passing the previous Activity as a context in your new class's constructor.
public NewClass(Context mainActivity, String ip, String pn, String, c)
It might work, but it seems a bit hacky.

Categories

Resources