0

I have a main activity that changes the image on the ImageButton on every click.

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

        static ImageButton mGetClickTime;
            mGetClickTime.setOnClickListener(new View.OnClickListener() {
            mUpdateBackground();
            }
        }
    }

public static void mUpdateBackground() {
        int[] imageIds = { 
                R.drawable.bg1,
                R.drawable.bg2,
                R.drawable.bg3,
                R.drawable.bg4,
                };
        Random generator = new Random();
        randomImageId = imageIds[generator.nextInt(imageIds.length)];
                mGetClickTime.setImageResource(randomImageId);
        }

This works fine, until the menu button is clicked and another activity is accessed

public class settings extends MainActivity{


@Override
   public void onCreate(Bundle savedInstanceState) {                
   super.onCreate(savedInstanceState);    
   setContentView(R.layout.settings);
   }
}

When the menu or back button is pressed, we return to the main activity. But once this has happened, the ImageButton no longer has the image updated with every click. Everything else still works, including text boxes updating on each click.

What am I doing wrong?

EDIT

Thanks for all your help. At the moment, it seems to continue working after I return from the sub-activity. (Hooray!)

But now I can't get the mUpdateBackground method to work when called from onResume(), or from the other activity. Here's where I'm at:

1 public class MainActivity extends Activity {
2   public static ImageButton mGetClickTime;
3 @Override
4   protected void onResume() {
5        super.onResume();
6       //Get shared preferences
7               mSharedPreferences = getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
8           dp = mSharedPreferences.getInt("DecimalPlaces", 0);
9               length_setting = mSharedPreferences.getInt("MSSelector", 1);
10              backgroundPic = mSharedPreferences.getBoolean("BackgroundPic", true);
11              //mUpdateBackground();  
12          }
12  @Override
13  protected void onCreate(Bundle savedInstanceState) {
14      super.onCreate(savedInstanceState);
15      setContentView(R.layout.activity_main);
16
17      //Get shared preferences
18      mSharedPreferences = getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
19      dp = mSharedPreferences.getInt("DecimalPlaces", 0);
20      length_setting = mSharedPreferences.getInt("MSSelector", 5);
21      mUpdateBackground();
22          mGetClickTime.setOnClickListener(new View.OnClickListener() {
23      mUpdateBackground();
24          }
25     }
26 }
27  public void mUpdateBackground() {
28      if (backgroundPic) {
29          int[] imageIds = { 
30                  R.drawable.bg1,
31                  R.drawable.bg2,
32                  R.drawable.bg3,
33                  R.drawable.bg4,
34
35          };
36          Random generator = new Random();
37          randomImageId = imageIds[generator.nextInt(imageIds.length)];
38          Log.d("1", "backgroundPic: "+randomImageId);
39      }
40      else {
41          randomImageId = R.drawable.bg0;
42          Log.d("1", "backgroundPicCALLED: "+randomImageId);
43      }
44      mGetClickTime = (ImageButton) findViewById(R.id.clicker);
45      mGetClickTime.setImageResource(randomImageId);
46  }

The problem I have with this is that if I uncomment line 11 I get a NullPointerException. Could that be because the mUpdateBackground() method at line 27 isn't static? If I make it static then at line 44 I get an error on findViewById, Cannot make a static reference to the non-static method findViewById(int) from the type Activity. I'm really stumped. I'm obviously not following the logic correctly but I've gone over it a few times and I can't see what it could be.

Tupac
  • 647
  • 12
  • 37
Dicky Moore
  • 956
  • 3
  • 10
  • 32
  • Have you tried putting the onClickListener in onResume? If it works unless you leave the activity and go back again I assume it has to do with a life cycle issue. – Raymond P May 17 '13 at 21:32
  • Thanks Raymond. I will try that but I'm unsure where the onResume gets called. – Dicky Moore May 17 '13 at 21:38
  • OK, I've tried that and it doesn't work. I've cut the onClickListener out of the onCreate method and have put it in the onResume method. The app still works and fails in the same way as above. – Dicky Moore May 17 '13 at 21:40
  • So I guess that means a lifecycle issue - do you know where I could look to try and understand what's happening here? – Dicky Moore May 17 '13 at 21:41
  • Also, I have been refactoring, and I've put the textboxes in a public static method and have defined them as public static variables, and now they are not working in exactly the same way as the ImageButton isn't working. – Dicky Moore May 17 '13 at 21:42
  • Is there a particular reason for declaring them static? If you declare the ImageButton global, so in the class but outside the onCreate method and not use static, unless you want to access it from elsewhere but I can't think of a situation where this is needed since this is an activity I think it will work. – Raymond P May 17 '13 at 21:48
  • Are you referring to the methods? I thought I should make them static so they can be accessed from anywhere in the structure. Forgive me if this is a misunderstanding of static. – Dicky Moore May 17 '13 at 21:52
  • I just tried removing static from the method and now I'm getting the cannot make a static reference to a non-static object error. – Dicky Moore May 17 '13 at 21:53
  • Try putting ImageButton mGetClickTime above the onCreate Method, so inside the class body and don't use static. – Raymond P May 17 '13 at 21:59
  • Also I dont see any reference (findViewById). Using static views can cause memory leaks anyhow, so it's not really good practice. – Raymond P May 17 '13 at 22:08
  • Ah, you're right. I'll edit that in. Whoops – Dicky Moore May 17 '13 at 22:27
  • That's edited in now. The ImageButton mGetClickTime; is set the line after public class MainActivity extends Activity { but now I've removed static from it I'm getting this error within the mUpdateBackground method: Cannot make a static reference to the non-static field mGetClickTime – Dicky Moore May 17 '13 at 22:30
  • you can also remove static from the mUpdateBackground method unless you wan't to use the method from another activity. But then again, I don't see why you want to update an activity's UI thats paused or stopped. – Raymond P May 17 '13 at 22:34
  • I was planning to call it from another activity. In the settings activity there is a button which allows you to turn off the ImageButton image (which calls the mUpgradeBackground activity with a setting to choose a blank image rather than one of the random ones). That should be ok, shouldn't it? – Dicky Moore May 17 '13 at 22:38
  • I personally always use shared preferences for settings so they are stored even if my app process is destroyed. You could do it too, then you can use onResume(is called on every start/restart) to check the shared preferences and decide if you show one of your images or the one selected by the user. Check this out: http://stackoverflow.com/questions/3851560/how-to-use-sharedpreferences – Raymond P May 17 '13 at 22:45
  • The problem I'm having now is that the MainActivity onResume seems to get called as soon as I try to call the settings activity, and I get a null pointer exception when trying to call the mUpdate method. Will try to work out what's going on. – Dicky Moore May 17 '13 at 23:26
  • One important note, you declare fields static only if it is common for all the objects of one class. Why would ImageButton be static in first place if you have only one instance of MainActivity? This is always a easy way to access field from outside the class, but this leads to sloppy code and it becomes buggy. This is for me good when you try to quickly patch someones code, not when you design it from sketch. – Marko Lazić May 18 '13 at 15:09
  • Ok thanks. So if I want to call a method from OnResume and onCreate, what is the alternative to declaring it as static? And can I call it from another activity the same way? Thanks for your help. – Dicky Moore May 18 '13 at 16:23

2 Answers2

1

Ha, now I see what is bothering you. Your problem is either onResume or onCreate happens second time and this resets your image to your default value you set in your XML. You can simply log and see which of these occurs. Once you see where your image is returned to default, simply create field in your activity class which will remember your current image id or what you want. Something like this

private int currentImage = R.drawable.firstImage;

public class MainActivity extends Activity{

   protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

    static ImageButton mGetClickTime;
    mGetClickTime.setImageResource(currentImage);
        mGetClickTime.setOnClickListener(new View.OnClickListener() {
        mUpdateBackground();
        }
    }
   }

public static void mUpdateBackground() {
    int[] imageIds = { 
            R.drawable.bg1,
            R.drawable.bg2,
            R.drawable.bg3,
            R.drawable.bg4,
            };
    Random generator = new Random();
    randomImageId = imageIds[generator.nextInt(imageIds.length)];
            mGetClickTime.setImageResource(randomImageId);
            currentImage = randomImageId;
    }

Hope this helps and enjoy your work.

Marko Lazić
  • 883
  • 7
  • 9
  • Thanks ever so much for your help. When I try to put the private int currentimage line outside of the public class MainActivity I get the error Syntax error on tokens. Is it possible to put this line outside of the Activity? – Dicky Moore May 18 '13 at 10:09
  • Thanks very much for your suggestion. The thing is, the image isn't being reset back to the default, it just stops being able to be changed. When this happens, the latest image just remains. – Dicky Moore May 18 '13 at 11:19
0

I got the answer from this thread: Android: What's the best hierarchy for this app?

The key was learning the concept of checking if an object is null before calling it.

The code I used was this:

    if (mGetClickTime != null) {
        Log.d("mGetClickTime: ", "is not null");
        mGetClickTime.setImageResource(randomImageId);
    }
    else {
        mGetClickTime = (ImageButton) findViewById(R.id.clicker);
        mGetClickTime.setImageResource(randomImageId);
        Log.d("mUpdateBackground", " was null");
    }
Community
  • 1
  • 1
Dicky Moore
  • 956
  • 3
  • 10
  • 32