Good day everybody! Here's my question:
I need to make a Tutorial for my app. For doing this, I've created a class called TutorialClass which contains some methods that I need to call from several other classes. The working flow is quite like this:
Class 1:
//...
if(Tutorial.tutorialStep==Tutorial.TUTORIAL_STEP1){
Tutorial.TutorialStep1();
Tutorial.tutorialStep=Tutorial.TUTORIAL_STEP2;
}
Class 2:
//...
if(Tutorial.tutorialStep==Tutorial.TUTORIAL_STEP2){
Tutorial.TutorialStep2();
Tutorial.tutorialStep=Tutorial.TUTORIAL_STEP3;
}
And so on...
All the classes I use, have not to extend Activity necessarily
You can find this piece of code in several class I use.
So, first of all I need to create an instance of TutorialClass
TutorialClass Tutorial = null;
So here is the question: how can I use this instance from all the classes in which I have to show my tutorial? As you can see, the value of tutorialStep has to be visible from all classes, and all classes have to see that value or change it, in order to let the tutorial go on.
Here is the code of my tutorial class:
public class TutorialClass{
Context context;
public static int tutorialStep;
final int TUTORIAL_STEP1=1;
final int TUTORIAL_STEP2=2;
final int TUTORIAL_STEP3=3;
//...
TutorialClass(Context context){
this.context = context;
}
public void Tutorial1() { ... }
public void Tutorial2() { ... }
public void Tutorial3() { ... }
//...
}
I've read that exist a Singleton class that allows to reach my objective, but I've noticed that it's not the best solution. Do you have any solution? Thanks to all!
you need to create another class that return instance of the TutorialClass
public class TutorielInstance {
private static TutorialClass instance;
private static Context context;
public static synchronized TutorialClass getInstance(){
if(instance==null){
instance=new TutorialClass(context);
}
return instance;
}
public static void setContext(Context c){
context=c;
}
}
and then in the activity you can use
TutorielInstance.setContext(this);
TutorialClass tutorialClass=TutorielInstance.getInstance();
Related
I have this class
public class InternetConnectionException extends RuntimeException {
int code = 0;
public InternetConnectionException(){
super("Internet connection is down");
}
public InternetConnectionException(String message){
super(message);
}
}
This error message shouldn't be hardcoded. It should be externalized in order for different languages to be supplied, because when this exception is thrown the message is being displayed on the screen.
Now, is there a way to externalize it as a strings.xml resource or should I change the design? (i.e. when this exception is thrown, just reference the string resource in the activity and display the resolved value)
I believe that a good design shouldn't allow pure Java classes such as an exception to know about the insides of Android framework, but I could be wrong.
Since you can't access string.xml directly but there is one way I can think of to achieve what you're trying to accomplish.
Put your all String values into string.xml
Maintain another java class(say, StringConstant.java) which will hold some of the contents of string.xml that you need to access in other non-Activity/Fragment classes.
Extend Application class(say, AppApplication.java) and initiate an object of StringConstant class here
Load the Strings from StringConstant class
Access the Strings from other class through the instance of StringConstant in Application class.
Here are some codes to demonstrate the idea
AppApplication.java
public class AppApplication extends Application {
public static StringConstant STRING_CONSTANT;
#Override
public void onCreate() {
super.onCreate();
STRING_CONSTANT = new StringConstant(getBaseContext());
STRING_CONSTANT.build();
}
}
StringConstant.java
public class StringConstant {
private Context context;
public static String appName;
// declare other String variables
public StringConstant(Context context) {
this.context = context;
}
public void build(){
setAppName(context.getString(R.string.app_name));
// set other String variables
}
public static String getAppName() {
return appName;
}
public static void setAppName(String appName) {
StringConstant.appName = appName;
}
}
and now accessing the strings from another class
public class InternetConnectionException extends RuntimeException {
int code = 0;
public InternetConnectionException(){
super(AppAplication.STRING_CONSTANT.getAppName());
}
public InternetConnectionException(String message){
super(message);
}
}
I have a class like
public class Enclosing {
public String methodA() {
Inner.getContext();
......
}
private static class Inner{
// some context init
public static Context getContext() {
.....
}
}
}
Now I want to test methodA without invoking the real Inner.getContext(). I have been searching all over but cannot find a working solution. I am using Java 8. Can I have some help please? Many thanks
You can apply the extend and override technique, here's how it works.
Given this code:
public class Enclosing {
public String methodA() {
Inner.getContext();
......
}
You can move the Inner.getContext() call to a protected method:
public class Enclosing {
public String methodA() {
getContext();
......
}
protected void getContext() {
Inner.getContext();
......
}
And then in your test case, you can extend the enclosing class, and override the protected method to do whatever you want with it:
#Test
public void test_something() {
Enclosing enclosing = new Enclosing() {
#Override
protected void getContext() {
// do what you need here
}
};
// your test code on enclosing where you control getContext
}
As an alternative to #janos' answer, you can inject a strategy (basically, the "prefer composition over inheritance" approach):
interface ContextStrategy {
void getContext();
}
and then inject an instance of this into the constructor of Enclosing:
class Enclosing {
private final ContextStrategy ctxStrategy;
Enclosing(ContextStrategy ctxStrategy) {
this.ctxStrategy = ctxStrategy;
}
String methodA() {
ctxStrategy.getContext();
// ...
}
}
and then implement this interface for the production case, as a nested class in Enclosing:
static class ContextStrategyImpl implements ContextStrategy {
#Override public void getContext() {
Inner.getContext();
}
}
and implement an alternative version for your mock case.
You should not mock a private class (whether it is a nested class like the one here or an actual inner class).
Instead, mock only the Context type if it's really needed (otherwise, use a real Context object). For example, such a test is shown below, using the JMockit library:
#Test
public void mockingTheContext(#Mocked Context anyContext) {
new Expectations() {{
// record any method call results expected from "anyContext"
}};
new Enclosing().methodA();
new Verifications() {{
// verify calls to "anyContext", if applicable
}};
}
In the test above, the fact that Context is created inside a nested class is irrelevant. In general, mocking private methods or classes should always be avoided, since they are only implementation details.
/**
* A preference change listener to resynchronize a contact list
*
*/
private static Preference.OnPreferenceClickListener resynchronizeContactsListener = new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
new AlertDialog() {
}
}
}
In a code snippet such as the above, I need to call a non-static method, or create an AlertDialog(). Both of which I am having difficulty doing since the listener is a static method.
For example, the AlertDialog.Builder() constructor requires an android context object to be created, but since the method is static there is no context. I considered passing in the context as a parameter, however I am not sure where to do so without damaging the fact that I am overriding a method.
Thanks in advance
You can implement the Preference.OnPreferenceClickListener into your own class statically and initialise it from your activity code when ready. (I am assuming that you need the listener object to be static for some reason, you may do away with that!)
private static MyPrefListener myPrefListener = null;
private static class MyPrefListener implements Preference.OnPreferenceClickListener {
private Context mContext;
public MyPrefListener(Context context) {
this.mContext = context;
}
#Override
public boolean onPreferenceClick(Preference preference) {
//USE mContext as the context object here
return false;
}
}
Then in your Activity code, do this:
myPrefListener = new MyPrefListener(this);
I hope the structure of the code is clear.
Basically, A static method cannot call a non-static method, but we can use a reference, which include a non-static method to the static method.
public class StaticMethodTest{
void NonStaticMethod(){
System.out.println("This is a non-sataic method.");
}
static void StaticMethod(StaticMethodTest s){
System.out.println("This is a static method.");
s.NonStaticMethod();
}
public static void main(String[] args) {
StaticMethodTest sObj=new StaticMethodTest();
StaticMethod(sObj);
}}
This is a java example, I think you can use this way to create a object, and use it reference into the static method.
Hope it can help you.
Basically, A static method cannot call a non-static method, but we can use a reference, which include a non-static method to the static method.
public class StaticMethodTest{
void NonStaticMethod(){
System.out.println("This is a non-sataic method.");
}
static void StaticMethod(StaticMethodTest s){
System.out.println("This is a static method.");
s.NonStaticMethod();
}
public static void main(String[] args) {
StaticMethodTest sObj=new StaticMethodTest();
StaticMethod(sObj);
}}
This is a java example, I think you can use this way to create a object, and use it reference into the static method. Hope it can help you.
Just remove the static keyword from your declaration.
A class or interface (note not the actual instantiated object, simply the class definition) is declared static when it's an inner class but has no reference to it's containing class. EG
public class Foo {
public static class Bar {
}
}
Bar cannot reference any of the state of Foo and can be instantiated independently with new Foo.Bar().
I have many classes which have the same static attribute (staticAttr) and i have another class which accepts the class name and accesses its staticAttr of the class name specified.
How can i do this. Please help me!
Thanks.
EDIT:
public class Group_name1 extends Activity implements View.OnClickListener,
{
public static Group_name1 staticVar;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.group_name1);
staticVar = this;
}
}
public class Group_name2 extends Activity implements View.OnClickListener,
{
public static Group_name2 staticVar;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.group_name2);
staticVar = this;
}
}
Now my problem is to have an access to the static variable of these classes in another class by just giving a class name string. Now the class should can be used to get the staticVar which contains the object.
Currently, i have created seperate classes for every class mentioned above to refer to the staticVar. But i feel its redundant and bad style of programming because every class i write for refering to the above classes does the same function. The only thing that changes is the Class name reference
Group_name1 grpActivity;
Group_name2 grpActivity;
These are my current implementations. But i want to just use the class name to refer the static variable
class GroupNameListener1 extends Thread
{
Group_name1 grpActivity;
public void run()
{
grpActivity = Group_name1.staticVar;
/*
do something
*/
}
}
class GroupNameListener2 extends Thread
{
Group_name2 grpActivity;
public void run()
{
grpActivity = Group_name2.staticVar;
/*
do something
*/
}
}
Like this :
ClassWithStaticVariable.VariableName
if you have
class A {
public static String a = "test"
}
then you can access it like this :
class B {
public void test() {
System.out.println(A.a);
}
}
If I am understanding you correctly you have something like
class A {
public static String str = "test"
}
and in you code you have a method like
void methodA (A someObj) {
in this method you can access the static variable
as
A.str
or
someObj.str
What you have is very bad design. Short of reflection there is no way to solve this generically as you designed it.
I believe what you are trying to do is attaching meta data to your classes. A very simple way to do that would be to keep a global map holding the data (and work with the class instead of its name):
public class MyClassMetaData {
private final static Map<Class<?>, String> dataMap = new HashMap<>();
static {
dataMap.put(MyClassA.class, "TestA"); // one method of initialization
dataMap.put(MyClass2.class, "Case2");
// one line per class...
}
private MyClassMetaData() {
}
public static String getMetaData(Class<?> theClass) {
return dataMap.get(theClass);
}
}
But you need to remember to add a line that puts the data into the map into the static block when you add another class.
If you need to initialize data dynamically, access to the map may need to be synchronized.
I am creating a custom class in main application class. Lets say My mainAccount.
Now, i am creating many activities. I want to mainAccount variable in every activity, how can i do that? One way is to put in intent and pass to each activity. Is there any better way, like making it global etC?
Best Regards
Look up Singleton classes. Basically, you want something like this.
public class Singleton {
private static Singleton instance = null;
protected Singleton() {
// Exists only to defeat instantiation.
}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
Then, for any class that needs access to the class, call:
Singleton var=Singleton.getInstance();
This is essentially global, without most of the negative consequences of global variables. It will ensure that only one object of that class can exist, but everyone who needs it can access it.
Have you thought about using preferences?
A great resource for more info is.
http://mobile.tutsplus.com/tutorials/android/android-application-preferences/
Or you can create a class that extends application as demostrated by
http://www.helloandroid.com/category/topics-covered/global-variables
Just define an Abstract class with those variables and methods whichever you want to access in activities.
For example:
public abstract class BaseActivity extends Activity
{
//static variables
// static methods
}
Now extends this BaseActivity class in your all activity:
public class HelloAndroid extends BaseActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
You can use "singleton" class, or "static" class (if you don't need to initialize it, instantiate or inherit or implement interfaces).
Singleton class:
public class MySingletonClass {
private static MySingletonClass instance;
public static MySingletonClass getInstance() {
if (instance == null)
instance = new MySingletonClass();
return instance;
}
private MySingletonClass() {
}
private String val;
public String getValue() {
return val;
}
public void setValue(String value) {
this.val = value;
}
}
String s = MySingletonClass.getInstance().getValue();
Static class:
public class MyStaticClass {
public static String value;
}
String s = MyStaticClass.value;