Android: references to findViewById - java

I have been doing this for all my activities when I reference an element from my UI, I create a class variable. This can sometimes lead to 10 - 20 class variables just for UI elements:
public class CommentActivity extends AppCompatActivity {
LinearLayout addComment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comment);
addComment = (LinearLayout) findViewById(R.id.addcomment);
addComment.setOnClickListener( // add an onclick listener here //);
}
}
Now, I have observed by looking at other people's code that sometimes they would do this instead:
public class CommentActivity extends AppCompatActivity {
// LinearLayout addComment; no more reference to class variable
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comment);
//they just findViewById and add on the onclick listener
findViewById(R.id.addcomment).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
Is the second method more memory efficient? There is no longer a class variable strong reference and therefore garbage collection can happen more easily. But I'm just wondering what the risk is of using the second method. If garbage collection happens when using the app, does the addComment linearLayout lose its click functionality?
I'm just trying ways to optimise my app's memory use.

Is the second method more memory efficient?
Not particularly. The LinearLayout addComment reference costs ~8 bytes.
There is no longer a class variable strong reference and therefore garbage collection can happen more easily
Not in this case, since other things are holding onto the LinearLayout. After all, findViewById() is getting the LinearLayout from somewhere.

Related

How to correct add a listener to a Fragment

I got two Fragments (basic-setup) with a FragmentPagerAdapter for use in a TabLayout.
tabLayout.setupWithViewPager(myViewPagerWithAdapter);
My Adapter takes an array of Fragments and titles as argument (also the FragmentManger for the super call).
MyViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager() ,fragments, titles);
My Fragments (indeed 2) got a WebView in their xml file. To use the WebViews outside the fragments (it's kinda odd to code the control of the WebViews inside fragments, because the MainActivity is mainly involved with my user interaction). To know when my WebViews in the fragments were inflated, I added a simple interface, called OnFragmentCreatedListener, which is triggered in public void onActivityCreated(Bundle savedInstanceState) of the fragments. I add the listener through following way:
private OnFragmentCreatedListener listener;
...
public void addOnFragmentCreatedListener(OnFragmentCreatedListener listener) {
this.listener = listener;
}
In my MainActivity I add this listener like this:
public class MainActivity extends AppCompatActivity implements OnFragmentCreatedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
MyFragment fragment = MyFragment.newInstance();
...
fragment.addOnFragmentCreatedListener(this);
...
}
#Override
public void onFragmentCreatedListener() {
// Do my stuff
}
Now when the screen rotates and the activity is restarted, the listener in the fragment stays null (wasn't initialized). Now I don't know what to do, because I don't understand this behavior. The code should do the same like in the first protected void onCreate(Bundle savedInstanceState) of the MainActivity. It's adding the listener but it stays null (like wtf?).
Thank you for spending your time!

Initialised ImageButton in other Activity throws nullPointerException when referenced in MainActivity

I'm very new to Android and Java coding in general, so bear with me if I don't understand basic concepts.. This is just a test to see if something works, so It might not initially make any sense.
I have two activities, Main and Other.
the Other Activity has an imageButton with visibility initially set to invisible.
When MainActivity is created, it should look for that imageButton in the Other activity, and set it's view to visible.
Though when debugging, all I get is a nullPointerException, because the button has null as value. How can I make it reference the button?
Part of Main Activity:
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pstep();
}
public void pstep() {
int pstep = 0;
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
panfav.setVisibility(View.VISIBLE);
}
Part of Other Activity:
public class navfav extends AppCompatActivity {
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navfav);
}
public void fab(View v){
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
panfav.setVisibility(View.VISIBLE);
}
XML linked to Other Activity:
<ImageButton
android:id="#+id/favpancake"
android:layout_width="wrap_content"
android:layout_height="137dp"
android:layout_alignParentStart="true"
android:layout_below="#+id/imageView3"
android:background="#android:color/background_dark"
android:contentDescription="#string/nav_cook_dish"
android:onClick="fab"
android:scaleType="centerCrop"
android:src="#drawable/dishpancake"
android:visibility="invisible" />
Log:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.ImageButton.setVisibility(int)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method
'void android.widget.ImageButton.setVisibility(int)' on a null object reference
at com.p2.rookie.MainActivity.pstep(MainActivity.java:23)
at com.p2.rookie.MainActivity.onCreate(MainActivity.java:16)
Shoot if I'm missing anything you need to use, I'll provide as much as i can :)
Best
The visibility of the buttons are always "VISIBLE", please give me the log
and in the navFav activity the "fab" method are not in the onCreate
you are getting nullPointerException because ImageButton with id favpancake is not present in MainActivity layout activity_main
public class navfav extends AppCompatActivity {
public static List<String> recipes;
// other code here
}
and then when you want to add recipe to shown in Other Activity listView,
recipes = new ArrayList<String>();
recipes.add(recipe);
Now when you open the other Activity all those recipes will be available in list name "recipes". which you can use to show in your listView.
One Activity can and should not reference elements in other Activities.
If you call 'setContentView' with a layout file, you can only reference the views in that layout file.
Try and tell us what you're trying to achieve and we might be able to help you out in improving your code.
(Posted on behalf of the OP).
Just read a bunch of other stuff elsewhere, and I think something made sense now! Instead of creating new intents and startActivity'ies when changing layout/pages, I just setContentView to new layouts/pages, and gather all methods from different activities in one activity - That's how basic this fail was I think? ;)
Then all views and methods can reference each other.

Trying to execute multiple layout from single class

I'm trying to execute more then one layout screens from single class using onClick() method
Here goes my code
Button bt1,bt2;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 = (Button)findViewById(R.id.button);
bt2 = (Button)findViewById(R.id.button1);
onClick(); //onClick(View) in MainActivity cannot be applied to ()
}
public void onClick(View v){
if(v.getId()==R.id.button){
setContentView(R.layout.next1);
}
else if(v.getId()==R.id.button){
setContentView(R.layout.next1);
}
}
Kindly help me out, Thank you
Fragment is what you have to use, in this case. Load either of the fragment based on button click.
If you go for setContentView in this scenario, then your code will be clumsy and it will be very tedious for you to keep track on view.

Java syntax explanation

I'm new to Java and I encountered the following code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = new Button(this);
button.setText("Touch That!");
button.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.this.onButtonClick(v);
}
});
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rootlayout);
relativeLayout.addView(button);
}
public void onButtonClick(View view){
//do something when button is clicked.
}
}
I didn't understand the syntax, View.OnClickListener() c'tor is called and it is followed by {} and overidding method.
what does this syntax stand for?
to which object this refers?
My guess is the button. but if I'm right why to use MainActivity.this instead of this? (the object that invoked the method)
This is an anonymous class declaration. It means that you will override some methods inside the class dynamically.
Take a look at this arcticle:
http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
About your second question, MainActivity.this refers to the instance of the Activity you are currently in. If you call only this, it would refer to the actual object. When you call MainActivity.this, you will get the instance of MainActivity you are in, even if there is more activities created. Take a look at Android's activity lifecycle.
What's the difference between this and Activity.this
Hope it helps.
By calling
new View.OnClickListener(){}
you are creating an object implementing interface OnClickListerner that requires you to implement the click method.
Someone can correct if I am wrong.

Global Reference findViewById

Is it possible to get a reference to an XML element such as a button using findViewById globally in the main java class?
I have so many references that I need to keep on calling them all over again multiple times because I can't use the reference I called in the onCreate method.
private long mode;
private final Button playBtn = (Button)findViewById(R.id.playBtn);
private final TextView aboutTitle = (TextView)findViewById(R.id.aboutTitle);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playBtn.setTypeface(robotoThin);
aboutTitle.setText("hello world");
}
I know that to fix the error would be to reference the button and the textview after the setContentView but the problem is that I need to repeat all my references for each method in the same class.
// try this way (here i'm declare your both view object as globaly for your class so it can be acccess any where in classs and is created onCreate() at first time and further it used directly)
private long mode;
private Button playBtn;
private TextView aboutTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playBtn = (Button)findViewById(R.id.playBtn);
aboutTitle = (TextView)findViewById(R.id.aboutTitle);
playBtn.setTypeface(robotoThin);
aboutTitle.setText("hello world");
}
You have to create member variables for the Views you want to reference and you initialize them in onCreate() once. Then you reference these variables where you need inside the Activity

Categories