im trying to remove values from an arrayList im my android app, but they keep re-appearing.
My arrayList is in a separate class,
in my Main Activty I create an instance of that class and remove a value from the array.
I exit the Main Activity and return the value re-appears.
My Question is how can I can some kind of static instance of the array class???
//ArrayClass
public class ArrayClass {
public final static ArrayList<String> words = new ArrayList<String>();
public ArrayClass() {
words.add("WORD");
words.add("WORD");
words.add("WORD");
}
//Main Class
ArrayClass wordc = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
wordc.removeWord(0);
}
Orest is correct you do want a singleton pattern, but remember when you access the class's methods you always need to use the getInstance() method.
For example a method within the Class:
public String getWord(index i) {
.......
}
Should be called statically as follows
ArrayClass.getInstance().getWord(i);
NOT like this
wordc.getWord(i);
This guarantees that there is one and only one instance (thus the singleton)
I might be confused on what you are doing but to access the static Array you don't want to create an instance of the class. Everytime you do that you are running the constructor which, in the example code, populates your static Array each time with 3 values.
I don't see exactly what you are trying to accomplish so maybe you could explain that a little better but I'm guessing this really isn't what you want your constructor doing. I think you want to access the Array itself statically
//Main Class
ArrayClass wordc = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
wordc.removeWord(0); //don't need this
ArrayClass.words.remove(0); // would remove the element at index 0
}
But this still wouldn't solve your problem. You need a method inside your ArrayClass class that adds items to your Array. Doing it in your constructor will add these items each time you create a new instance of your class.
If this doesn't answer your question then maybe you can explain your assignment a little better.
Have you tried the Singleton patter? You will have one static reference of ArrayClass and it's internal state won't be violated by activity lifecycle.
public class ArrayClass {
private static ArrayClass instance;
public static ArrayClass getInstance() {
if(instance == null) instance = new ArrayClass();
return instance;
}
//...rest goes as is.
Related
I have a class called myConstants and in it i list all my constants so when i need them I just reference MyConstants.MYCONSTANT. However, i would like to implement something like this for methods. i am repeating a lot of code, for instance, i have a formatCalendarString(Calendar c) method in 3 activities. seems redundant and unecessary. but i cant make them static because i get static calling non-static errors and the only other way i can think is to make a MyConstant object then call public functions off that object, like this...
MyConstants myConstants = new MyConstants();
myConstants.formatCalendarString(Calendar.getInstance());
is there some way i can just call the formatCalendarString() inside MyConstants class without generating an object?
You can use singleton pattern to cache instances. Keeping methods in something like parent activity does not make any sense (as primary role of activity is user interaction).
Example:
public class MyConstants {
private static MyConstants ourInstance;
private MyConstants() {
//private constructor to limit direct instantiation
}
public synchronized static MyConstants getInstance() {
//if null then only create instance
if (ourInstance ==null) {
ourInstance = new MyConstants();
}
//otherwise return cached instance
return ourInstance;
}
}
You just need a private constructor and public static method that would only generate instance if it is null.
Then, call MyConstants.getInstance().whateverMethod(). It will create only single instance.
However when using singleton, please keep memory leaks in mind. Do not pass activity context directly inside singletons.
If you want to have all methods in activities, you can put then in abstract class BaseActivity, which extends Activity, and then make your activities extends BaseActivity. However, if these methods doesn't correspond to something about activity, I suggest some Singleton or Util class
I agree with Pier Giorgio Misley. It's also good to add a private constructor, because you don't obviously want to instantiate an object.
Can't you just use a parent class? That way you can just inherit the methods and manage in one source. Then you don't have to use static functions then.
Edit: Like Tomasz Czura said, just extend the Class.
public class ParentClass {
public void commonMethod(){
}
}
public class OtherClass extends ParentClass{
}
You can use the Static keyword.
Static methods can be referenced from outside without istantiating the new object.
Just create a class:
public class MyClassContainingMethods{
public static String MyStaticMethod(){
return "I am static!";
}
}
Now call it like
String res = MyClassContainingStaticMethods.MyStaticMethod();
Hope this helps
NOTE
You CAN call non-static from static by doing something like this:
public static void First_function(Context context)
{
SMS sms = new SMS();
sms.Second_function(context);
}
public void Second_function(Context context)
{
Toast.makeText(context,"Hello",1).show(); // This i anable to display and cause crash
}
Example taken from here, you will obiouvsly have to fit it into your needs
Here is my scenario.
I have an android activity in which I want to abstract my I/O dependencies. The dependencies are represented by this interface (edited for brevity and simplicity):
public interface ITimeDataServer {
TimeRecord[] get(int userID);
void save(TimeRecord record);
}
What I want is for my activity to be able to call these interface methods, and leave the implementation to be supplied by the calling code. (Pretty standard, I think).
ITimeDataServer myServer;
int myUserID;
void loadRecords() {
TimeRecord[] records = myServer.get(myUserID);
// etc...
}
My difficulty is, how can I ensure that myServer gets set?
This seems like a common problem, but I can't find a clean solution.
My first thought would be that myServer would be passed in through the constructor, but Android activities aren't really instantiated with constructors.
I've come up with several solutions, but they're all icky in some way:
Icky Solution 1
Create a static method to launch the activity class which takes an ITimeDataServer parameter and stores it in a static variable from which the activity can access it:
private static ITimeDataSource theDataSource;
public static void launch(Activity currentActivity, ITimeDataSource dataSource) {
theDataSource = dataSource;
Intent intent = new Intent(currentActivity, MainActivity.class);
currentActivity.startActivity(intent);
}
This is icky because (a) the data source is static and not actually associated with the instance, and (b) a consumer could initiate the activity by the standard activity API rather than this static method, which will cause NullPointerException.
Icky Solution 2
I can create a Provider class which provides a singleton instance of ITimeDataSource, which needs to be initialized by the calling library before use:
public class TimeDataSourceProvider {
private static ITimeDataSource myDataSource = null;
public void initialize(ITimeDataSource dataSource) {
myDataSource = dataSource;
}
public ITimeDataSource get() {
if (myDataSource == null)
throw new NullPointerException("TimeDataSourceProvider.initialize() must be called before .get() can be used.");
else
return myDataSource;
}
}
This seems a little less icky, but it's still a little icky because the activity's dependency is not obvious, and since there may be many paths to launch it, it's highly possible that some of them would forget to call TimeDataSourceProvider.initialize().
Icky solution 3
As a variation on #2, create a static IODependencyProvider class which must be initialized with ALL dependencies on app startup.
public class IODependencyProvider {
static ITimeDataSource myTimeData;
static IScheduleDataSource myScheduleData; // etc
public static void initialize(ITimeDataSource timeData, IScheduleDataSource scheduleData /* etc */) {
myTimeData = timeData;
myScheduleData = scheduleData;
//etc
}
public static ITimeDataSource getTimeData() {
if (myTimeData == null)
throw new NullPointerException("IODependencyProvider.initialize() must be called before the getX() methods can be used.");
else
return myTimeData;
}
// getScheduleData(), etc
}
This seems superior to #1 and #2 since a failure to initialize would be much harder to sneak by, but it also creates interdependencies among the data types that otherwise need not exist.
...and other icky variations on that theme.
The common themes that make these solutions crappy:
the need to use static fields to pass non-serializable information to an activity
the lack of ability to enforce initialization of those static fields (and subsequent haphazardness)
inability to clearly identify an activity's dependencies (due to reliance on statics)
What's a nooby Android developer to do?
As long as these dependencies implement Parcelable correctly, you should be able to add them to your intent, then unparcel them as ITimeDataServer and get the correct class.
I found a nice solution here, in the least-loved answer.
I define the library activity as abstract and with no default constructor, but a constructor that takes an interface, like so:
public abstract class TimeActivity extends AppCompatActivity {
private ITimeDataSource myTimeDataSource;
public TimeActivity(#NonNull ITimeDataSource dataSource) {
myTimeDataSource = dataSource;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
// do stuff with myTimeDataSource!
}
}
Then, the calling code can create a concrete subclass with its chosen implementation that does have a parameterless constructor. No static members, easy-peasy!
This allows you to abstract and inject all sorts of crazy behaviours! Woooo!
(Note that the concrete subclass activity needs to be manually added to AndroidManifest.xml, like all activities, or the app will crash when it tries to launch.)
I have two Classes. Class A is an Activity that has integer variables that need to be used in Class B (not an Activity). I have been able to use Bundles to transfer data of variables from one Activity to another Activity before. The problem is that this time, Class B is not an Activity and extends ImageView so that the draw() function can be used. Because of this, I am unable to use normal Activity functions, such as Bundle-Intents or SharedPreferences to transfer data in primitive variables from Class A to my Class B. I receive an error saying that "getIntent() is undefined for type".
So my question is, how can Class B use the variables in Class A if I am unable to bundle? Is there another way?
Someone said they did not understand my question so hopefully the below example will help demonstrate better.
public Class1 extends Activity {
//so Class1 has some primitive data, and is an Activity w/layout
int var1;
int var2;
Bitmap bitmap;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
}
}
A different class needs to draw onto canvas, but also needs to use the
information in var1 and var2 to be able to draw properly. But how to obtain that information?
public Class2 extends ImageView {
/*I am unable to use normal Activity functions, so I
*cannot onCreate, for example. I also cannot bundle,
*getIntent(), or use getSharedPreferences(). So how do I get var1
*and var2 value? */
}
Update: I was able to get this to work using getters. I attempted this before, but it was not returning the correct values. If anyone else ever gets stuck with this similar issue, remember to setup your variables with "static". I'm still learning all the differences, but without static my getter was not working. Once I added static to my variables, everything worked out. So that's one observational tip (even without fully understanding the logic as to why). Thank you to all the responders for your tips.
You can do this in different way.
First of all you can use static variable to do this. Such that you can declare a variable in class A public static String variable; and from class B you can get the value of this variable like this way ClassA.variable.
Another way you can use by passing a context of class A to B and then use SharedPreference.
Or create a new class which extends android Application. From class A you can set different variable value in application class. Now you can retreive those values from Application class. Hope this can help you.
Some code Sample using static variable
public Class1 extends Activity {
public static int var1 =20;
public static int var2 = 30;
}
Now get the variable value from class two
public Class2 extends ImageView {
Class1.var1;
Class.var2;
}
Second way using getter.
public Class1 extends Activity{
int var1 =10;
int var2 =20;
public int getVar1() {
return var1;
}
public int getVar2() {
return var2;
}
}
Now you can get the variable value in Class2
public Class2 extends ImageView {
Class1 class1= new Class1();
class1.getVar1;
class1.getVar2;
}
Also you can use SharedPreference. Hope it can help you. Thanks.
Various options exist:
The Activity can pass the information to Class B:
class B {
public void tellMeInformat(int usefulNumber) {
// Do something
}
}
Or, you can pass the Activity to the ImageView:
class A {
initiation {
B mySpecialImageView = /* Set it upo */;
B.setParentActivity(this);
}
}
class B {
private myA = null;
public void setParentActiviy {
myA = A;
}
private void doSomething {
int usefulNumber = A.getUsefulNumbner();
// Do something
}
}
So i have made a class DrawView which extends View and i want to draw some graph in that class with the points i stored as int array
i made this array like a sort of public variable with the help of How to declare global variables
So when i want to get connected with MyApp in Activity and change my array, i simply use
MyApp appState = ((MyApp)getApplicationContext());
but the problem is that this won't work when i call it in my DrawView.java class.
Any ides how to solve this?
I really don't know why that answer is so up voted as it's not a good solution.
The Application object is to run the Application, not to store data, you can solve this MUCH easier with a simple Singleton object, try this:
public Class MyData{
private int[] data;
private static MyData me;
public int[] getData(){
return data;
}
private MyData(){} // private constructor
public MyData get() {}
if(me==null) me = new MyData();
return me;
}
}
than from any object you can call:
int[] data = MyData.get().getData()
and feel free to expand to more than just a int[] ... put any other object that you want to be globally accessible. But remember, DO NOT KEEP REFERENCES TO THE CONTEXT!
I am trying to write an Activity that has some views, a fillView() method that sets the views (which is not static because it must utilize getContentResolver), and a static method that makes a random choice from a cursor and then runs the fillView() method.
I had problems with this due to fillView not being static and pickRandom being static, so I tried to initialzize an instance of the class, but now it crashes on the line instance.fillView();
Sample code below. Any help would be appreciated. Perhaps there is a much easier way to accomplish what I am trying to do.
Thanks,
Josh
public class myView extends Activity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.myView);
fillView();
}
public void fillView(){
//creates views, runs cursor and applies results to the view created
}
public static void pickRandom() {
// runs cursor, picks random entry, next I want to apply the result to
// view, so I run...
myView v = new myView();
v.fillView();
}
Make a static instance variable and set in in oncreate:
private static myView instance;
oncreate()
instance = this;
static pickrandom()
instance.fillView();
in your pickRandom you try to create new instance of your class. Instead of this you should do the following:
this.fillView();
I don't see any purpose you have your pickRandom static.
If, however, you need it for some reason you can pass a reference to your view like this:
public static void pickRandom(myView v) {
// runs cursor, picks random entry, next I want to apply the result to
// view, so I run...
v.fillView();
}