0

I would like to add elements to the three ArrayLists declared in the code bellow but I seem to be having some issues related to variable scope. Disclaimer: I'm very new to Java and it could just be that I'm doing something very silly. Also note that I'm using the Parse Android API. (I added some comments to the code to better highlight the issue I'm trying to resolve). Thanks!

public class MatchesActivity extends Activity implements OnItemClickListener {

ArrayList<String> titles = new ArrayList<String>();
ArrayList<String> descriptions = new ArrayList<String>();
ArrayList<Bitmap> images = new ArrayList<Bitmap>();
String school;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.matches_layout);

    ParseQuery query = new ParseQuery("Profile");
    query.whereEqualTo("userName", ParseUser.getCurrentUser().getUsername().toString());
    query.getFirstInBackground(new GetCallback() {
        public void done(ParseObject obj, ParseException e) {
            if (e == null) {
                school = obj.getString("school");
                ParseQuery query2 = new ParseQuery("Profile");
                query2.whereEqualTo("school", school);
                query2.findInBackground(new FindCallback() {
                    public void done(List<ParseObject> scoreList, ParseException e) {
                        if (e == null) {
                            // scoreList.size() == 3 here
                            for (int i = 0; i < scoreList.size(); i++){
                                titles.add(scoreList.get(i).getString("fullName"));
                                descriptions.add(scoreList.get(i).getString("sentence"));

                                ParseFile profileImg = (ParseFile) scoreList.get(i).get("pic");
                                try { 
                                    profileImg.getDataInBackground(new GetDataCallback() {
                                        public void done(byte[] data, ParseException e) {
                                            if (e == null) {
                                                Bitmap bMap = BitmapFactory.decodeByteArray(data, 0,data.length);
                                                images.add(bMap);
                                            } else {
                                                Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(),Toast.LENGTH_SHORT).show();
                                            }
                                            // AT THIS POINT THE ARRAYLIST "IMAGES" IS BEING ASSIGNED VALUES
                                        }

                                    });
                                } catch (NullPointerException npe) {
                                    images.add(BitmapFactory.decodeResource(getResources(), R.drawable.ic_prof));
                                }           
                            }           
                            // HERE, THE SIZE OF TITLES AND DESCRIPTION IS 3, HOWEVER, IMAGES HAS NO ELEMENTS (WHEN I EXPECTED IT TO HAVE 3)
                        } else {
                            Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            } else {
                Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    });
    // ALL LISTS ARE EMPTY AT THIS POINT (BUT I WOULD LIKE TO USE THEM HERE)
}

Problem solved: As it was brought up by Yogendra Singh and twaddington, the getDataInBackground method was running as a secondary thread which did not have a chance to finish before I was reaching the specific place in my code where I needed the information being retrieved there. As my ultimate task was to dynamically fill up a listView with information retrieved from my Parse database, I simply decided to follow the hints here and do all that from within the getDataInBackground. That worked! Thanks everyone for the help.

Community
  • 1
  • 1
Everaldo Aguiar
  • 4,016
  • 7
  • 26
  • 31
  • 1
    If I had the guess, the `ParseQuery` is executing asynchronously. That means calling `getFirstInBackground` will return immediately and your `onCreate` method will finish before the background task has executed and your lists are populated. – twaddington Nov 05 '12 at 02:38
  • @twaddington Great guess! Let me do some investigation on that. The method IS running on a different thread indeed. – Everaldo Aguiar Nov 05 '12 at 02:41

1 Answers1

1

You have declared the Lists as Class member attributes. These attributes can be directly accessed within any non-static method of your class. You are doing fine in using them in the onCreate method.

One observatory note: You may want to define the variables as private.

There may be some other issue which you are correlating the scope of the variables. If you think there is some issue, please share the specific issue being observed.

EDIT: As suspected, this issue is due to the fact that the lists are getting populated in the background. By the time, it reaches the last line (to print the size), its quite possible that lists are not populated yet.

PLEASE NOTE: A GetCallback is used to run code after a ParseQuery is used to fetch a ParseObject in a background thread. This means that GetCallBack is being run the background (asynchronous mode).

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • Thanks for the comments. I have a very brief description of the issues inside the code itself. That is, while I'm inserting 3 items to each of the lists during runtime, when I reach the very end of the code above (see comment right above the last line) the lists seem to be empty once again. – Everaldo Aguiar Nov 05 '12 at 01:46
  • @EveraldoAguiar: You last line is outside of your method definition so I believe the issue/or felt issue is that your method `onCreate` is not being called. If it is being called, then probably its not reaching the statements where values are added to the list. If this is also not the case then somewhere, you are re-initializing the member variables. I may help if you can share the code where the event is being triggered and where you are getting the empty variables. – Yogendra Singh Nov 05 '12 at 01:51
  • Thanks again. The `onCreate()` is definitely being called and all statements are being reached (I debugged this portion of the code with Android Toast messages to see. The event is triggered automatically when this Activity is created. Here is a [LINK](http://pastebin.com/UbhR4eft) with the entire code snippet. Note the issue highlighted on lines 89-92 – Everaldo Aguiar Nov 05 '12 at 02:29
  • 1
    @EveraldoAguiar: If you notice `query.getFirstInBackground`, you calling the method in background(asynchronous) mode. So you are reaching the codes in the end, while `done()` method is being executed. That way you are reading the size as "0" as they are not populated yet. – Yogendra Singh Nov 05 '12 at 02:43
  • That must really be it! Do you happen to know if there is anything I could do in order to stall the execution until the background thread is done? – Everaldo Aguiar Nov 05 '12 at 02:46
  • 1
    @EveraldoAguiar: One simple work around could be to check the size of your list in a while loop with a small sleep time until the values are populated. This may not work if in your program, lists are not populated for some genuine reason. One other way could be to define a status flag as class variable, defaulting it to `false`. Set the value to `true` in the finally section of `done` method. In the end, put a while loop before your last statements, checking the status with a small sleep interval. Loop will exit when `status` is set to `true`. Put your remaining statements after the loop. – Yogendra Singh Nov 05 '12 at 02:55
  • Strangely enough, I still seem to be having the same issue even after trying this. I defined a variable `int done = 0;` and set it to `1` once the size of my list is 3. I then have a while loop in my main thread that runs continuously while `done != 1`. This loops endlessly (i.e., done is never seen with a value of 1 outside the secondary thread. What a mystery! – Everaldo Aguiar Nov 05 '12 at 03:36
  • @EveraldoAguiar I am suspecting that some issue is occurring in your `done` method. Would you mind wrapping your code in try/catch block and put `done = 0;` in the finally block of `done` method just to make sure its not ending somewhere else. – Yogendra Singh Nov 05 '12 at 03:43
  • I ended up fixing the problem by simply performing the operations that I needed (i.e., dynamically populate a list View) from within the background thread. Although I still do not know why the previous approach was not working. Thank you so much for the help! – Everaldo Aguiar Nov 05 '12 at 04:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19065/discussion-between-yogendra-singh-and-everaldo-aguiar) – Yogendra Singh Nov 05 '12 at 04:15