I'm following tutorials on how to put functions that are used frequently in activities all in one place.
For example, a toast message that comes up throughout my project, instead of having the function in each and every activity, just having it called in one place, GlobalFunctions.java.
So, I get it with simple functions, for example, in GlobalFunctions.java :
public class GlobalFunctions {
public void simpleMessage() {
System.out.println("simpleMessage text goes here");
}
}
And the I call it like this from Activity1:
GlobalFunctions simplemessage = new GlobalFunctions();
simplemessage.simpleMessage();
But what about? :
public class GlobalFunctions {
public void simpleMessage() {
Toast.makeText(getApplicationContext(), "simpleMessage text goes here", Toast.LENGTH_LONG).show();
}
}
I've looked at several posts including getApplicationContext() error Android and no matter what I put in the Context part of Toast I get a Cannot resolve method message. Also if there's any good tutorials for Dummies on this subject I'd be grateful.
The key is static .
Static values allow you to use static methods variables ..etc in whole project.
You can use following concept:
public static class GlobalFunctions {
public static void simpleMessage(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
And you have to invoke it like:
GlobalFunctions.simpleMessage(/*YourActivity.this*/ /*or*/ /*getActivity()*/, "toast");
One solution would be to pass the Context as a parameter from the Activity or Fragment.
And instead of instantiating GlobalFunctions, writing and using static methods can be a better approach.
Create a Java Utils class:
public class Utils {
public static void showToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
}
// for example on the Activity code
Utils.showToast(this, "This is the toast text");
Keeping context in field beyond activity can be reason of memory leak, but there is some workaround.
You can create Singleton with application or application context and initialize it in onCreate in your custom application class. But you have to remember that you can't use this context to build views - it is not stylized.
Other way is just pass context as argument.
Sorry for missing code, response from phone :)
try this Create class like this to pass Context and Toast message as parameter like this
public class GlobalFunctions {
public static void simpleMessage(Context context,String message) {
Toast.makeText(Context, message, Toast.LENGTH_LONG).show();
}
}
call this function like this
GlobalFunctions.simpleMessage(YourActivity.this,"your Mesaage");
Related
I'd like to make some text via Toast inside message handler, and my message handler is declared in the separate class.
public class HandlerAlert extends Handler {
final static byte IP_OK=0;
final static byte IP_WRONG=-1;
Context ctx;
public HandlerAlert(Context ctx) {
super();
this.ctx=ctx;
}
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case IP_OK:
if (msg.arg1==(CheckSendMode.REGULAR).ordinal())
{
Toast.makeText(ctx/*null*/,
"OK",Toast.LENGTH_LONG).show();
Log.i("MessageOk",ctx.getClass().getName());
}
........
I have two activities, and both can call this message. I expected that my Toast.MakeText would produce output in the activity which context (parameter ctx) is used. However, I see the output in both activities despite of ctx passed. Name of activity passed in Context ctx is observed by Log.i("MessageOk",ctx.getClass().getName()); I thought that Toast.MakeText works in all activities despite of context, and even tested null context (absolutely expected exception was obtained).
My question is the following: does Toast.MakeText send output in the activity which is currently open? I'm ready to provide any part of code if necessary.
Thanks in advance.
Create a class ShowToast
inside that class create a method
public Class ShowToast{
Context mContext;
public void displayToast(String msg){
Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();
}
Inside your activity
ShowToast dispToast = new ShowToast(this);
btn.setOnClickListener(new View.OnClickListener(){
publiv void onClick(View v){
dispToast.showToast("Hello World");
}
});
It is hypothesis only: I suppose that in fact toastuses application context, not activity one. I try
Toast.makeText(ctx.getApplicationContext(), "OK",Toast.LENGTH_LONG).show();
and it works as if it would be activity context. By the way,
Log.i("MessageOk",ctx.getApplicationContext().getClass().getName());
produces class android.app.Application. Please confirm or deny my supposition.
As I'm really annoyed of passing the Context for most of the operations in Android (Database, Toast, Preferences). I was wondering if it's a good way of programming to initialize these elements once (e.g. in Application-Class).
It works quite good, I don't have to pass the element from Class to class and I can't see any disadvantages. Thats the reason why I wanted to ask you guys. Why shouldn't I use this?
For the people who don't know what I mean:
MainApplication:
public class MainApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
VolleySingleton.init(this);
Toaster.init(this);
PrefUtilities.init(this);
}
}
Toaster:
public class Toaster {
private static Toaster mInstance = null;
private Context context;
private Toast currentToast;
private Toaster(Context context) {
this.context = context;
}
public static void init(Context context) {
mInstance = new Toaster(context);
}
public static void toast(String message){
if (mInstance.currentToast != null){
mInstance.currentToast.cancel();
}
mInstance.currentToast = Toast.makeText(mInstance.context, message, Toast.LENGTH_SHORT);
mInstance.currentToast.show();
}
}
I'm also interested in the question, why the context for Toast or other stuff is needed? I can use the application context for the Toast and have access in every single Activity / Fragment. Why has the Android-Team implemented it this way?
So basically two questions:
1. Do I have any disadvantages with my implementation (memory, time) ?
2. Why do classes like Toast require a context at all?
1. Do I have any disadvantages with my implementation (memory, time) ?
Well, you are always initiating your db, even if you dont use it at all during that session, same goes for the other classes. Couldnt think of anything else, since you would use application context anyways, at least for database.
2. Why do classes like Toast require a context at all?
Toast requires a context since it touches the UiThread, so it needs a reference to access the thread.
I have an app that uses custom Exceptions, such as this:
public class SomeException extends Exception{
private int iCode;
private String iMessage;
public SomeException(){
iCode = 201;
iMessage = **//Get the localized string R.string.error_201??**
}
#Override
public String getMessage() {
return iMessage;
}
#Override
public int getCode() {
return iCode;
}
}
Obviously, I want lo localize the error message. I have possible solutions but non of them satisfy me.
1) Pass "Context" to the constructor, and do ctx.getString(R.string.error_201)
--> Fail, as this Exceptions are sometimes thrown from MODEL classes, so they don't have a Context
2) Pass "Context" when retriveing the message in getMessage() function,
--> Fail, It's necesary to override the super method, to work as all other Exceptions.
Solution I have now: All activities in my app have this onCreate:
public void onCreate(...){
Utils.RESOURCES = getResources();
...
}
Very dirty code... I don't like the solution. My question is then,: is there a way to access the resources without the Context? And most important, How would an application such as mine solve this problem?
What about
public class MyException extends Exception {
private int iCode;
public MyException(int code) {
this.iCode = code;
}
#Override
public String getMessage() {
return "MyException code " + String.valueOf(iCode);
}
public String getLocalizedMessage(Context ctx) {
String message;
if (iCode == 201)
message = ctx.getString(R.string.error_201);
else if (iCode == 202)
message = ctx.getString(R.string.error_202);
// ...
}
}
Even if there was way to access context in different way, you should not do it. If you need to emit exceptions where you cannot pass Context, you should be able to access context before you display such error. I cannot see reason why you should create localized error messages from constructor. You can log to logcat not localized versions if you need. And where you want to display something in UI, you should have context at hand.
You can access only system wide resources without Context.
You need a Context, so I would suggest You to get it as soon as possible, and make it available through a static method or variable. You do the same thing in every Activity, but there is a cleaner method. You should make a custom Application, and override its onCreate() to make the resources public:
public class App extends Application {
private static Resources myResources;
#Override
public void onCreate() {
myResources = getBaseContext().getResources();
super.onCreate();
}
public static Resources getMyResources(){
return myResources;
}
}
The other thing you have to do is to set the Application in your manifest:
<application
android:name="{your_package}.App"
...
Now you can access the resources in all of your Activity without any preparation. Your custom Exception class could also use the externalized resources.
For every Activity I add to my app I'm noticing a lot of similar code being used in the initialization of the Activity. A helper class with a static method to wrap this similar code seems the way to go.
I first thought of a singleton class. I could add static methods/variables and use them across the application. I haven't really tried to see how would this work in an Android application. Searching a little bit more I saw something about creating a class extending Application. For this I did a simple test:
public class MyApp extends Application {
public static String DEMOTEXT = "WORKING!";
public static void ShowToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
MyApp.ShowToast(this, MyApp.DEMOTEXT); // Placed on onCreate of some Activity
This works exactly as I expected. Is this the way to go on Android or is there a better convention? Anything else I should consider when doing this?
By the way, should I use the final keyword on the string? What about the method?
EDIT: I just read this:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
Should I use a singleton then?
Application is primarily used for a global application initialization. You would create your own class, override Application.onCreate() and initialize your static application data there.
Dont forget to declare it in the AndroidMainfest.xml:
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:name="your.package.path.to.MyApp">
A static helper class is made the way you did.
The convention is to use lower case letter at first position, so MyApp.showToast(...).
You would use final for the String if you would want to avoid madifications on other places (since it should be a contant).
// this would allow ...
public static String DEMOTEXT = "WORKING!";
// ... to do this somewhere else
MyApp.DEMOTEXT = "NOT WORKING!"
I haven't tried this but I think you should be able to do something like this as well.
public class MyActivity extends Activity {
private static final String DEMOTEXT = "WORKING!";
#Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Toast.makeText(this, DEMOTEXT, Toast.LENGTH_SHORT).show();
}
}
Now for all activities that need to use that initialization could just extend your base activity class.
public class SomeActivity extends MyActivity {
...
// Should display the toast on create
...
}
Yes just use a singleton. Well in this case if your methods are static, you don't even need a singleton. Just a class with static methods.
When programming for Android sometimes you have to use static methods. But when you try to access you resources in a static method with getString(R.string.text) you'll get an error. Making it static doesn't work.
Does anyone knows a good way around this? The resource files in Android are very helpful for creating things in different languages or making changes to a text.
One way or another, you'll need a Context for that... For static methods this probably means you need to pass along a Context when calling them.
You could use Resources.getSystem().getStringArray(android.R.array.done);
This is how I access resources from inside static methods. Maybe not ideal, but.
First, I extend Application and set some public static field(s), and create a method to initialise them:
public class MyApp extends Application {
// static resources
public static String APP_NAME;
public static void initResources(Context context) {
APP_NAME = context.getResources().getString(R.string.app_name);
}
}
And in my manifest I register the extended Application:
<application
android:name=".MyApp"/>
In my starter activity (MainActivity), I make a call to initialise the static resources:
#Override
protected void onCreate(Bundle savedInstanceState) {
MyApp.initResources(this);
}
Then anywhere in your project, after MainActivity.onCreate(Bundle b) has run, you can call static methods that access your specified static resources:
public static void printAppName() {
Log.w("tag", "my app name: " + MyApp.APP_NAME);
}
Pass in a Context (i.e. Activity) instance as a parameter object to static method. Then invoke getString on the parameter.
The post below gives a tip for creating an Application class to save your current context. Your new Application class will then be accessible from any other static method.
How can I get a resource content from a static context?
One way is you can pass context to your static method.
check this out it definitely works
public class Sounds {
public static MediaPlayer getSoundTouch(Context context){
return MediaPlayer.create(context, R.raw.touch);
}
public static MediaPlayer getSoundLeak(Context context){
return MediaPlayer.create(context, R.raw.leak);
}
public static MediaPlayer getSoundFinish(Context context){
return MediaPlayer.create(context, R.raw.finish);
}
}