How to create an instance variable in one activity Android? - java

So this seems like an odd question, but there's something I'm not understanding about Android Studio (I just started working with it).
If I want to create a variable in an activity, and then access it within different methods in my activity, I should be able to do that, right?
For instance, consider the following code:
public class bakers extends AppCompatActivity {
private Bunz bunz;
BigDecimal baker1Cost = BigDecimal.valueOf(20); //cost of baker1
BigDecimal baker1Bunz = BigDecimal.valueOf(.1); //number of bunz produced by each baker1
TextView baker1CostText = (TextView) findViewById(R.id.baker1Cost);
TextView baker1Owned = (TextView) findViewById(R.id.baker1Owned);
TextView baker1BunzText = (TextView) findViewById(R.id.baker1Bunz);
TextView bunzCount = (TextView) findViewById(R.id.bunzCount3);
TextView moneyCount = (TextView) findViewById(R.id.moneyCount3);
#Override
protected void onResume() {
super.onResume();
setContentView(R.layout.activity_bakers);
bunz = Bunz.getInstance();
bunzCount.setText("Bunz: " + bunz.getBunz());
moneyCount.setText("Money: " + bunz.getMoney());
baker1BunzText.setText(baker1Bunz.toPlainString());
baker1CostText.setText("Cost: " + (baker1Cost));
baker1Owned.setText("Owned: " + bunz.getBaker1());
}
...
In this code, I try to declare and initialize a bunch of variable before my onResume() method, but this doesn't work. I've found that I can declare variables before the onResume() method, but then for instance if I want to update the value of these variables in the onResume() method, that's fine, but if I want to access that variable in another method, such as onClick, I can't do that, and have to redefine the variables.
Is there something I'm doing wrong here? In essence, my question boils down to this: I want to have an instance variable for one activity (not throughout all activities) that I can access and modify anywhere within the activity.
EDIT: It seems as thought initializing and declaring variables before the onResume method works with things like ints, but I can only declare things like Buttons and Textviews - is there any way I can get around this?
Thanks

Why not initialize your variables in the onCreate method of your Activity? Here you can get an unterstanding of the activity lifecycle.

Related

Android, why I cant call my stringarray inside a method outside of onCreate?

Outside my onCreate method my stringarray isnt able to be called , why is that ?
I tried to initialize the stringarray again in the method outside onCreate with getResources(); but I cant call that either,
im guessing there is some fundemental knowledge im lacking as im fairly new in the programming world, can u help me or explain why the string array can't be called outside onCreate and/or how to work around it ?
example inside onCreate :
final String[] list = res.getStringArray(R.array.fact);
outside onCreate :
public void facts(){
getResources();
final String[] list = res.getStringArray(R.array.fact);
}// marked res. in red saying "qualifier must be an expression" and without that I cant call "list"..
I believe your issue is variable scope. You've declared your string array in the onCreate() method, giving it "method scope" and then you're tying to access it in another method. I would suggest declaring your string array as a class level variable so that you can access it from any method within that class.
To avoid the NullPointerException issue pointed out by Ben P. in a comment, you could initialize your array variable in the onResume() method so that you have it ready to go before you need to use it anywhere else.
Make sure to take a look at the reference links below the code example. I think they'll help explain "why" better than I can in a quick answer here.
public class MainActivity extends AppCompatActivity {
private static String[] list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
// onResume() runs after onCreate() and onStart() in the Android Activity lifecycle.
// If your array has not been initialized yet, do it now.
if (list == null || list.length == 0) {
list = getResources().getStringArray(R.array.fact);
}
}
public void facts() {
// Do something with your array...
for (String arrayItem : list) {
String fact = arrayItem.toUpperCase();
}
}
}
References:
The Activity Lifecycle: https://developer.android.com/guide/components/activities/activity-lifecycle
Variable scope: https://www.java-made-easy.com/variable-scope.html
Replace
final String[] list = res.getStringArray(R.array.fact);
by
final String[] list = getResources().getStringArray(R.array.fact);

Android: Updating textviews in multiple activities

I need some pointers on doing the following:
lets say i have 10/20 (number doesn't matter) of activities.
each of these activities has a textview that should work like a counter.
each of these activities has a button to go to the next activity.
this counter starts when the app is launched, and increment itself every second.
So what i did so far is:
have in my main activity a method that instantiate a class that extends Thread.
In that class in the run() method, i increment a variable when a second passes.
Now i'm stuck on what i should do next. Any pointers would be appreciated thanks.
Edit: i need a way to communicate from inside the run method, to whichever activity is now currently on screen, to update its textview.
Just a bit of theory here for standard Object Oriented Programming : stick to the recommended principles like Loose Coupling which makes your project code less tied to each other. You can read more on that later.
Now, using Events, you can setup a system that is synonymous with the natural Publisher/Subscriber design pattern. Like this:
The activity that needs to notify the other activities is called Publisher and the other activities that need to be notified are called Subscribers.
From here:
There are already built and tested libraries to do Events in android. Like my favorite EventBus.
Step 1 Add this line to your app-level build.gradle file:
compile 'org.greenrobot:eventbus:3.0.0'
Then create a simple Plain Old Java Object aka POJO class like this:
public class UpdateTextViewEvent{
private String textToShow;
public UpdateTextViewEvent(String text){
this.textToShow = text;
}
//add your public getters and setters here
}
Step 2 Notify others:
When you want to notify anyone of the changes, you simply called this method:
EventBus.getDefault().post(new UpdateTextViewEvent("Some new Text"));
Step 3 Receive notifications
For those who want to be notified of this event, simply do this:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
NOTE: to actually handle the event:
#Subscribe
public void onEvent(UpdateTextViewEvent event){
String text = event.getTextToShow();
//now you can show by setting accordingly on the TextView;
}
This is so much easier to do, do decouple your code by eliminating static references in your different activities
I hope this helps! Good luck!
make that Textview in second class as
public static Textview text;
and call it in main activity as
SecondActivity obj=new SecondActivity();
obj.text.settext("");
You can create one another activity e.g. BaseActivity extend with Activity class and your all 10/20 activity extends with created BaseActivity Class.
You can use your textview with protected access specifiers.
What you need to do is inside the counter class, create an a method and passed in a TextView as the parameter. Then create an int variable and set the counter as the instance:
Like this
public static class Counter extends Thread{
private static int x;
#Override
public void run(){
x = counter;
}
public void setCounter(TextView tv){
tv.setText(String.valueOf(x));
}
}
Now call this method setCounter(TextView) in all the activity's onCreate() method you'll like to display the counter, and passed in your the layout TextView as the argument. Like this
...
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState):
....
TextView cTextView = (TextView)findViewById(R.id.texT1);
Counter c = new Counter();
c.setCounter(cTextView);
}

Trouble with findViewById, explained diagramatically

Hello everyone.
I've posted a basic diagram of my Android project above. It's pretty sad but that's what 5 minutes in paint get you.
Anyway, I'll walk you through it. I have xml with a series of imageViews which have onClickListeners in my board.Java class. If one of the imageViews are clicked on, an instance of pawn.java is instantiated, I pass the context to the instantiated pawn object, then call its possibleMoves() method.
At the end of this method I generate a list of int's which happen to be the id's of the imageViews. the final portion of possibleMoves() is the following:
for (String s : chunks) {
String possibleSquare = "s" + s.substring(2, 4);
Toast.makeText(boardContext, possibleSquare, Toast.LENGTH_SHORT).show();
int id = boardContext.getResources().getIdentifier(possibleSquare, "id", boardContext.getPackageName());
System.out.println(id);
ImageView backgroundImg = (ImageView) findViewById(id);
backgroundImg.setBackgroundColor(Color.rgb(255, 255, 255));
}
return list;
The issue I'm having is that AndroidStudio says my findViewById(id) cannot be resolved. I've tried putting the context boardContext (the context I pass to my instantiated pawn object) in front of the findViewById, and I've tried using findViewById(R.id.id).
Suggestions?
findViewById(int id) are functions for View objects - here.. so you can not call it on nothing or any object. When you have reference to an Activity and you call findViewById(int id) it pulls the activity's contentView and calls it on it..
so your to your solution, Inflate the View containing your ImageView or get reference to your activity or if your context that you are passing is an Activity as context then you can cast your activity to the context and call your prefered method

updating UI thread while in asynctask

as the title states, im trying to update something in my UI thread while running an asynctask.. i've read quite a bit on asynctask and it seems i should be able to change a
variable from the onPostExecute() method. obviously this is not the case.
Here is my sample code:
TextView tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated);
Login login = new Login();
login.execute(userName, password);
and here the the login class
public class Login extends AsyncTask<String, void, String>{
public String doInBackground(String... params){
logMeIn(params[0], params[1]);
}
public void onPostExecute(String update){
tv.setText(result); //this is not working!!
}
whats actually happening is tv is underlined red and eclipse says i need to create a local variable.. but i thought the onPostExecute is ran from the UI thread? confused :?
im trying to do what i found at this website. I'm not entirly sure what i'm doing and i would love a point in the right direction! thanks in advance.
This line here
TextView tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated);
is obviously declared either
Outside of a method -which would result in tv being null or
In a method that isn't part of the AsyncTask- which would mean the
task doesn't have access to it
You should define it as a member variable (outside of a method)
TextView tv;
then initialize it inside of a method
tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated);
This will give your task access to it as well as the rest of your class.
If your AsyncTask is a separate file than your Activity then you will want to see this answer on using an interface and create a callback to update the TextView in your Activity.
Place TextView tv; into the scope of the class and outside of the function. Leave tv = (TextView) findViewById(R.id.thingsThatNeedToBeUpdated); where it is. You should then be able to access tv from onPostExecute().
This is because the TextView variable tv is defined in another class that does not have Login as an inner class. If Login is an inner class of the class containing the variable tv, it should be able to see the variable tv.
An easy way to solve this would be to make your AsyncTask an inner class of your main class.
To bring your TextView instance into scope, pass your tv variable into your Login instance constructor and add the constructor and variable in as below.
public class Login extends AsyncTask<String, void, String>{
private TextView tv;
public Login(TextView tv){
this.tv = tv;
}
public String doInBackground(String... params){
logMeIn(params[0], params[1]);
}
public void onPostExecute(String update){
tv.setText(result); //this should work
}
}
You have to pass the variable to this instance, otherwise it is out of scope. You won't be able to access it unless you declare and instantiate a new variable within the Login class.

Passing a String Array Between Java Classes Android App

I am writing an Android app where I need to pass a string array between two classes. The string initializes fine and I can output the contents of the string fine in the one class but as I try to pass it to another class I get a Null Pointer Exception error. The following is the stripped down version of my code:
accelerometer.java:
public class accelerometer extends Service {
public String movement[];
public void onCreate() {
movement = new String[1000000];
}
public void updatearray() {
movement[arraypos]=getCurrentTimeString();
//Toast.makeText(this, movement[arraypos] , Toast.LENGTH_SHORT).show(); //this correctly displays each position in the array every time it updates so I know the array is working correctly in this file
arraypos+=1;
}
public String[] getmovement(){
return movement;
}
}
wakeupalarm.java:
public class wakeupalarm extends Activity {
private TextView herestext_;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wakeup);
herestext_ = (TextView) findViewById(R.id.TextView01);
accelerometer accelerometercall = new accelerometer();
String movearray[] = accelerometercall.getmovement();
herestext_.setText(movearray[2]);
}
}
I have a feeling I'm missing something very simple but any help would be greatly appreciated!
Thanks,
Scott
You're creating a new accelerometer class, which is completely uninitialized since there is no constructor, then you access its member. Of course it'll be null.
Not sure how your two classes are related, but if the activity is called by the service, then you need to pass the string through the intent (through an extra, for example).
Side note: Class names should always start with a capital letter. Method/variable names should have camel case, i.e. "updateArray". Also, you can format your code here by selecting it and pressing CTRL+K.
Your first problem, I think, is that you are creating an array with a million slots in it. Do you really mean to be doing that? It's going to take a lot of memory---quite possibly more than is available. You should instead look to having a Vector of Strings that you extend as necessary.

Categories