juztcode
juztcode

Reputation: 1355

declaring a variable as constant after a certain time- what's the workaround

The situation is coded as following:

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;


import android.os.Bundle;

import com.makeIT.www.R;

public class MainScreenActivity extends AppCompatActivity {
    /*final*/static Toolbar app_toolbar = null; //would like to declare constant here but,

    private Toolbar return_toolbar(){

        return findViewById(R.id.app_toolbar);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activityscreen_main);
        app_toolbar = findViewById(R.id.app_toolbar);/*findViewById isn't available till here*/

So, I'd like to make the view static final, but as you can see findViewById isn't available until the layout is set. Hence, I can only make it static. (In this case, not making final wouldn't hurt but still if there's a workaround, I'd like to know it.)

EDIT:what I wanted to do here was to make app_toolbar available as static(i.e. without any instance association) but also as a constant, but you see for both to happen app_toobar should be defined in the class and not in one of the methods. One way would be to manually invoke the onCreate (if it was possible at all) but again the Bundle would not be availble to us. Is overloading the onCreate possible? If yes, how do we fetch the Bundle since we might wanna save the state

Upvotes: 0

Views: 71

Answers (3)

Stephen C
Stephen C

Reputation: 719229

Basically, you are asking if it is possible to change a final variable.

Answer: it depends.

  • If the final is a compile time constant, then no. There is no practical way to do it. The constant's will be inlined by the bytecode compiler and changing the field containing the constant will have no effect ... except on other code that accesses the field reflectively.

  • If the final is not a compile time constant, then you cannot do it in Pure Java. However, you can use reflection to alter the modifier flags on trhe Field object for a final variable and then change the variable's value.

However modifying a final field via reflection is unsafe. An Java JIT or AOT compiler may emit native code that assumes that the value of a final does not change. If you change the value via reflection, the changed value may not be visible. Furthermore, this may not be something that can be fixed via the memory model; e.g. by adding actions with happens before relations.

Modification of final variables discussed explicitly in the Java language spec; see JLS 17.5.3.

My recommendation: don't do it. Figure out another solution to your problem.

Upvotes: 1

npinti
npinti

Reputation: 52185

Not sure that this is what you are after, so I am going to state the following assumption: What you want is to be able to access the toolbar as a static variable, regardless of the state of the activity to which it belongs.

What I would do, would be to create a factory class whose aim is to create the toolbar. This would entail, however, that you make changes such that:

  1. You get the toolbar by invoking the factory (which can be static if you like). You can wire up the factory to return a toolbar set up however you would like.

  2. In the activity, you remove any code used to construct the toolbar (this would need to be moved to the factory class explained in 1) and then, simply call the factory from your activity.

The drawback with this approach, however is that:

  1. You might need to use some extra logic to check if the component is rendered.

  2. It will not be possible to access the object's parent (might not be a deal breaker, but sometimes you might need to access the parent container), at least not through the factory itself.

EDIT: I haven't done Java in quite a while (and haven't touched Android in ages but...) what I meant was something like this:

public class ToolbarFactory {
    public static Toolbar getToolbar() {
        // In here you build your toolbar. You could move the existing code within your application which at the moment is building the toolbar.
    }
}

Whenever you want to get the toolbar, you can just do: ToolbarFactory.getToolbar() and this will give you the toolbar you are after.

Then, in your activity, I am assuming that you have something like so (pseudo code below):

Toolbar t = new Toolbar();
t.setThis(this);
s.setThat(that);
someContainer.add(t);

The chunk above would need to be moved to the factory class and replaced by the following:

someContainer.add(ToolbarFactory.getToolbar());

Upvotes: 1

whd.nsr
whd.nsr

Reputation: 694

This is a Java related actually, not Android.

If a variable is declared as final, you have to assign a value to it at declaration and you cannot change the value. However, you can edit the properties of the object assigned to it.

you can make it private static, and make only a public static getter that returns the reference of the static value, so you can only get it from outside but assign it only from the class (MainScreenActivity) itself.

Upvotes: 1

Related Questions