Passing a variable from an activity to a class - java

I am knew to Android.
How do i pass a static variable from one activity to a class.
I have a list of buttons and when i click one button, i want to open a new activity and at thye same time, pass a variable relating to that class. I have tried using shared preferences but in vain. The string variable i would like to is is called url. This is the code i have from the class
public class AppConstant {
public static final String BASE_URL = url;
}
The BASE_URL will be used in other classes that is why it is static and i want it to stay that way.

shortest way would be to remove final keyword
public static String BASE_URL = url;
this will allow you to write to this field from any method in your app
AppConstant.BASE_URL = "abc";
note that AppConstant isn't proper name for such usage, BASE_URL isn't constant...
btw. keeping data in static field is a veeery poor aproach, don't do this... use Bundle for passing data between Activities, IPC communication (binding) for Services, SharedPreferences, SQLiteDatabase and probably few other methods...

Since other solutions haven't worked for you, here is something a bit different:
Make a saparate file named "ext" or something. inside make a public abstract class like so:
public interface ext {
HashMap <String, String> myHash = new HashMap<>();
}
This way myHash will be created when the app is launched and will live as long as the app does so when you move from activity to activity, you can add values this way and access them in the next activity:
ext.myHash.put("BASE_URL", url);

If it's static it shouldn't be in a Activity,
I assume you mean accessing a static variable from an Activity?
If so you can simply call AppConstant.BASE_URL in your Activity, if it is shown in red press Control+Enter to fix the import in Android Studio.
On the other hand, passing a variable from an activity to a class can simply be done via methods. So just call a method in the activity and use a String as a parameter like so
Otherclass.doSomethingWithString(urlInYourActivity)
But I assume the thing I mentioned at the start is what you want to do

Related

How can I pass a HashMap as parameters

I have a class API, where you set and get the info you need to later be used on a API call
I want to make it easier to the next person who's gonna use this.
So instead of doing this:
api.addURL("urltorequesttoken");
api.addHeader("client_id","sdfsfsdfsd")
.addHeader("client_secret","sdfsdfsfsfd")
.addHeader("grant_type","client_credentials")
.addHeader("scope","READ");
api.addBody("bodyToSend")
I want to do this:
String URL = "";
URL = "put your URL here";
So I pass the URL and other variables as a parameter to another method where I will be doing what I did in the first block of code,so they don't need to know about the API class and its methods, but I dont know how to handle the hashmap, how can I do that user friendly? and then pass that as a parameter, also, what type of parameters should the methods receiving this info have? (Map<String key, String value>) or (String key, String value)?
EDIT(ADD):
So there's a class that a DEV is going to create, let's call it CreateToken
, so that class currently has:
api.addURL("urltorequesttoken");
api.addHeader("client_id","sdfsfsdfsd")
.addHeader("client_secret","sdfsdfsfsfd")
.addHeader("grant_type","client_credentials")
.addHeader("scope","READ");
api.addBody("bodyToSend")
There's another class called BASE, where Im doing the core services, in order for this to be easier for the person when they create their class, I dont want to have that block of code on their class, but instead, on mine, so in their class all they have to do is set the URL, headers and body(for POST method), so instead of this:
api.addURL("urltorequesttoken");
they will do:
URL = "urltorequesttoken";
and there's a method on their class to send me this or for me to get it i,e.
fillAPICallInfo(URL, headers, body);
I will receive that on the BASE class, but I dont know how to handle the Map variables, don't know how to make it easy for the DEV so they just put the key and value, and how do I receive that on my class (as a Map or as Strings)?
So you simply can pass a Map<String, String> as parameter:
public void fillAPICallInfo(String url, Map<String, String> headers, String body) {
// Assuming there is an instance of class DEV named api available
api.addURL(url);
headers.forEach((h, v) -> api.addHeader(h, v));
api.addBody(body);
}

Using same sqlite for three activities

I am using three activities which are opened at the same time. All activities are retreive data from sqlite. I don't close or re open my connection when i am going from activity a->b or from b->c.
I just dispose my db when activity is destroying.
Activity A
SqliteConnection db;
OnCreate method
db = new SqliteConnection(mypath);
OnDestroy
db.Dispose();
db=null;
Onbuttonclick
startActivity(new Intent(this, ActivityB));
Same code is running when i am going from activity b->c.
Inside the same activity i use sqlite plenty of times.
Is this a good practice? Should i dispose my connection immediatelly after a use? Or should i close my connection on pause and reopen on resume? Or can i pass the same opened connection to the next activity? Which is the best approach?
Question modifieded
class databaseHelper
{
private static SqliteConnection db;
public static SqliteConnection openDatabase(Context context)
{
if(db==null)
db = new SqliteConnection(mypath);
return db;
}
}
And inside my activity on create
databaseHelper.openDatabase(this).myquery....
I don`t roll with Java nor xamarin. Here is a Kotlin code, it is pretty self-explanatory.
class DatabaseHelper { //Public class
companion object { ///This is equiavalent to java static.
private var instance: YourDatabase? = null
fun getDbInstance(context: Context): YourDatabase? //This functions returns the initialized DB instance.
{
if(instance == null)
instance = YourDatabase(context) // initializing the DB only one time
return instance
}
}
}
Just create a public class and name it for example "DatabaseHelper". Inside the class, create one static variable of your database type. Create a public function that returns the static variable. Inside the function, first, check if the static instance is null and if it is null, then initialize it with your database instance. This way, when you need to use your database instance, just, access the static function, provide it with the context and it will return you the initialized database instance.
In Kotlin
DatabaseHelper.getDbInstance(this).yourDbFunction()
UPDATE
Since this answer took off, I would like to suggest improvements to my previous solution. Instead of passing a context of activity to initialize the database, use application context. If you give an activity context to the static database instance, a memory leak will occur because the database instance holds a strong reference to the activity and the activity will NOT be eligible for garbage collection.
Proper usage:
val myDb = MyDb(applicationContext)
In general we should encapsulate access to a local store in another class such as a DAO/Repository/Service instead of having them directly in the Activity. this promotes loose coupling between views and data/network access. This also decouples the lifecycle of your DB connection, from the lifecycle of the currently running activity, giving you more control and opportunity for reuse.
Try using a bound Service to and have your DB connections there. Because it is a bound Service, it'll only be around if there is an Activity around that binds to it. Each Activity will bind to the same instance of the Service so it means you wont have duplicate connections. When no Activities are bind to it, it'll automatically be destroyed, destroying the connection along with it.
For a more modern, structured approach, using Jetpack components, you can look at https://github.com/googlesamples/android-sunflower

How to use Strings from strings.xml in another class

I'm currently writing an App, it gets JSON from a website, and then lists the contents in a listview. Now since the API itself only returns names like this: "twisted_castle" instead of "Twisted Castle", I created a new class to substitute the generic names to the right names, which I previously added to the strings.xml.
Now I can get Strings via String test = getString(R.string.key) in the MainActivity, but since I created a new class for the Substitute to happen, I somehow can't use getString somehow.
I already discovered that I'll need to get/use the context of MainActivity somehow, but really any solution I found didn't work, and also I'm a bit irritated on how the whole context thing works.
Anyone can help me with this and maybe has a good explanation on how contexts work?
You can use Context as:
mcontext.getString(R.string.something);
all you have to do is init context in the class some where like:
static Context mcontext;
public void setmContext(Context context){
this.mcontext=context;
}
and call setmContext(this) from your activity or where ever you have context attribute

How do I use Enum in a proper way?

I'm very to Java and I use enum for the first time like this:
public class Web {
public String baseUrl;
public static enum Environment {
DEVELOPMENT("http://development") ,
PRODUCTION("http://production"),
SANDBOX("http://sandbox");
public final String baseUrl;
private Environment(String baseUrl)
{
this.baseUrl = baseUrl;
}
}
}
The enum Environment has the three constants DEVELOPMENT, PRODUCTION,SANDBOX. The Web class also has the baseUrl to which the Environment's baseUrl to be set ( not sure this is the good practice to do so ).
For setting up the baseUrl I'm currently doing like this :
new Web().setBaseUrl(Web.Environment.PRODUCTION.baseUrl)
I'm not sure this is the right way to use the enums with the classes. Are there any way to directly set Web baseUrl to enums baseUrl.
Am I missing something here.
Thanks in advance
I think you're on the right track, but you're losing some of the strength of Java's enum by accessing the URL in this manner. Instead, use the type of the enum to help ensure that you pass correct values to your method. That is, pass the enum alone, and let the method extract whatever value from it. For example:
new Web().setEnvironment(Web.Environment.PRODUCTION);
Now you can only pass Environments to your Web class, rather than any ol' string.
[Edit] Then your Web.setEnvironment method looks like this:
public void setEnvironment(Environment environment) {
this.baseUrl = environment.getBaseUrl();
}
This way, I can't come along and call new Web().setEnvironment("marvo") by accident. It enforces a certain level of correctness.
And vishal_aim is right. Even with Enums you should practice data hiding and encapsulation, so make the instance variable private, and provide an accessor like getBaseUrl() to retrieve the value.
Rather than using directly Enum's member baseUrl you should make it private and have a getter method in enum class. other than that I think it's ok to use enum this way
Make the enum a top level class/enum.
Add a getter for the baseUrl field.
I think there is nothing wrong with how you use Enum. However the code looks little clumsy:
new Web().setBaseUrl(Web.Environment.PRODUCTION.baseUrl)
I would take the Enum out of the Web class and omit the redundant 'baseUrl' field in the Web class- you do not need it since you have the value in your Enum. Instead of the baseUrl I would have a urlType member of type Environment. Also would be nice to add accessor method to the baseUrl inside the Environment enum
Along with what Bohemian and vishal_aim said, you might be unnecessarily exposing the baseUrl member (or getBaseUrl() method after you refactor it in). Instead pass the enum to the Web class and have it dig the URL from the enum. That way, if you keep the enum inside the Web class, you can keep the baseUrl private.
public void setEnvironment(Environment env) {
baseUrl = env.getBaseUrl();
....
}

Access Application class from class other then Activity

In my application I need data which is accessible for a few activities. I've read that a good solution is to use Application class for this. So I use it like this:
public class MyApplication extends Application {
private String str;
public String getStr(){
return str;
}
public void setStr(String s){
str = s;
}
}
and I can access this variable from activity like this:
MyApplication appState = ((MyApplication)getApplicationContext());
String str = appState.getStr();
It's ok, but I also have xml parser class:
public class MyXMLHandler extends DefaultHandler {
and if I try to do the same here
MyApplication app = ((MyApplication)getApplicationContext());
String str = app.getStr();
I'm getting The method getApplicationContext() is undefined for the type MyXMLHandler
How can I access my variable?
Well, usually an XML parser class should be independent of any special context. That means a developer should be able to use it no matter whether he's developing an application or a service or library or whathever.
The XML parser class should not make any assumptions as to the context it is being used in and where it gets parameters from (you'd restrict your parser to function only if it has access to an Application instance). The parser should not fetch its parameters, the parameters should be set by the caller.
You wouldn't want your XML parser class to show messages to the user, either, would you? Right: "What does an XML parser have to do with user interfaces?" Instead, you'd throw exceptions and make sure they are handled properly, for example depending on whether there's a user interface or not (logging).
So what you'd do is pass the parameters you need when constructing an instance of your XML parser. But you do not pass your application instance as a parameter (think again of dependencies), but you pass the necessary parameters from your application class.
In your example above:
MyApplication app = ((MyApplication)getApplicationContext());
MyXmlHandler handler = new MyXmlHandler(app.getStr());
You should really make sure to keep "tool stuff" separate from anything that would prevent you from using it universally. What would happen if you wanted to use your XML Parser class in another project where your parameter is not provided by the application context but some other class?
I'm sure that you can have a week-long discussion about object-oriented design and how things should be done - but that's basically how I'd do it...

Categories